package service

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"gorm.io/gorm"
	"math/rand"
	"path"
	"strconv"
	"sync"
	"vrcm/src/vrcm/app/admin/models/draw"
	"vrcm/src/vrcm/app/admin/models/live_schedule"
	"vrcm/src/vrcm/app/admin/models/subject"
	vrcDto "vrcm/src/vrcm/app/admin/service/dto/vrc"
	vrmDto "vrcm/src/vrcm/app/admin/service/dto/vrm"
	"vrcm/src/vrcm/app/admin/service/dto/wechat"
	mediaProcService "vrcm/src/vrcm/app/admin/service/media_proc"
	vrcService "vrcm/src/vrcm/app/admin/service/vrc"
	vrmService "vrcm/src/vrcm/app/admin/service/vrm"
	wechatService "vrcm/src/vrcm/app/admin/service/wechat"
	"vrcm/src/vrcm/common/apis"
	ext "vrcm/src/vrcm/envconfig"

	//"github.com/google/uuid"
	"github.com/tidwall/gjson"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
	"vrcm/src/vrcm/app/admin/models"
	"vrcm/src/vrcm/app/admin/models/likes"
	"vrcm/src/vrcm/app/admin/models/live"
	cloudLiveService "vrcm/src/vrcm/app/admin/service/cloud_live"
	imDto "vrcm/src/vrcm/app/admin/service/dto/im"
	"vrcm/src/vrcm/app/admin/service/dto/live"
	mediaProcDto "vrcm/src/vrcm/app/admin/service/dto/media_proc"
	streamHubDto "vrcm/src/vrcm/app/admin/service/dto/stream_hub"
	vrbmDto "vrcm/src/vrcm/app/admin/service/dto/vrbm"
	imService "vrcm/src/vrcm/app/admin/service/im"
	streamHubService "vrcm/src/vrcm/app/admin/service/stream_hub"
	vdaService "vrcm/src/vrcm/app/admin/service/vda"
	vrbmService "vrcm/src/vrcm/app/admin/service/vrbm"
	cDto "vrcm/src/vrcm/common/dto"
	common "vrcm/src/vrcm/common/models"
	"vrcm/src/vrcm/common/service"
)

var client = &http.Client{}

const secretKey = "o9d9fjewlsdhioiqwjioeeijlkjwlr9c1"

type LiveBasic struct {
	service.Service
}

// GetPage 获取LiveBasic列表
func (e *LiveBasic) GetPage(c *dto.LiveBasicGetPageReq, list *[]live.LiveBasic, count *int64) error {

	var err error
	var data live.LiveBasic
	db := e.Orm.Model(&data).
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		)

	if len(c.TenantId) > 0 {
		db.Where("tenant_id = ?", c.TenantId)
	}
	if c.LiveState > 0 {
		db.Where("live_state = ?", c.LiveState)
	}
	if c.LiveType == 0 {
		db.Where("live_type != 2")
	}

	if c.OrderFiled == 1 {
		db.Order("create_time desc")
	} else {
		db.Order("live_time desc")
	}
	err = db.
		Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("LiveBasicService GetPage error:%s \r\n", err)
		return err
	}

	return nil
}

func (e *LiveBasic) GetPageForEnterprise(c *dto.LiveBasicGetPageReq, list *[]live.LiveBasic, count *int64) error {
	var err error
	var data live.LiveBasic
	db := e.Orm.Model(&data).
		Scopes(
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).Joins("LEFT JOIN view_limit ON live_basic.id = view_limit.bind_id").
		Where("live_basic.corp_id_secret = ? and live_basic.is_delete=2", c.CorpId)
	//Where("(view_limit.view_page = 1 or  (view_limit.view_page = 2 and live_basic.corp_id_secret = ?)) and live_basic.is_delete=2 and (live_basic.live_state=2 or live_basic.live_state=3)", c.CorpId)
	err = db.
		Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("LiveBasicService GetPage error:%s \r\n", err)
		return err
	}

	return nil
}

// Get 获取LiveBasic对象
func (e *LiveBasic) Get(d *dto.LiveBasicGetReq, model *live.LiveBasicWithStream) error {
	var data live.LiveBasic
	streamInfos := make([]live.LiveMonitorRecord, 0, 3)
	var p []live.Personalization

	//获取直播间基本信息
	e.Orm.Where("id = ? and is_delete = 2 and tenant_id=?", d.GetId(), d.TenantId).Find(&data)
	if data.Id <= 0 {
		return errors.New("未找到直播间信息")
	}

	model.BasicInfo.LiveBasic = data

	//获取个性化设置
	err := e.Orm.Model(&live.Personalization{}).Where("live_id=?", data.Id).Find(&p).Error
	if err != nil {
		return err
	}
	for _, v := range p {
		if v.Kind == 1 {
			model.BasicInfo.GuidId = v.Id
			model.BasicInfo.EnableGuid = v.IsEnable
		}
		if v.Kind == 2 {
			model.BasicInfo.VirtualNumId = v.Id
			model.BasicInfo.EnableVirtualNum = v.IsEnable
		}
		if v.Kind == 3 {
			model.BasicInfo.IMId = v.Id
			model.BasicInfo.EnableIM = v.IsEnable
		}
		if v.Kind == 4 {
			model.BasicInfo.LikesId = v.Id
			model.BasicInfo.EnableLikes = v.IsEnable
		}

		if v.Kind == 5 {
			model.BasicInfo.CommentId = v.Id
			model.BasicInfo.EnableComment = v.IsEnable
			model.BasicInfo.IsAudit = v.IsAudit
		}

		if v.Kind == 7 {
			model.BasicInfo.CountDownId = v.Id
			model.BasicInfo.EnableCountDown = v.IsEnable
		}

		if v.Kind == 8 {
			model.BasicInfo.ReservationId = v.Id
			model.BasicInfo.EnableReservation = v.IsEnable
		}
	}
	if model.BasicInfo.EnableGuid == 0 {
		model.BasicInfo.EnableGuid = 2
	}

	if model.BasicInfo.EnableVirtualNum == 0 {
		model.BasicInfo.EnableVirtualNum = 2
	}

	if model.BasicInfo.EnableLikes == 0 {
		model.BasicInfo.EnableLikes = 2
	}

	if model.BasicInfo.EnableComment == 0 {
		model.BasicInfo.EnableComment = 2
	}

	if model.BasicInfo.EnableCountDown == 0 {
		model.BasicInfo.EnableCountDown = 2
	}

	if model.BasicInfo.EnableReservation == 0 {
		model.BasicInfo.EnableReservation = 2
	}

	//获取直播流信息
	e.Orm.Model(&live.LiveMonitorRecord{}).Where("tenant_id = ? and basic_id =? and is_delete = 2", data.TenantId, data.Id).Order("view_no asc").Find(&streamInfos)
	model.StreamInfos = streamInfos
	if len(streamInfos) > 0 {
		model.StreamInfo = streamInfos[0]
	}

	//获取点赞记录
	if data.RoundId > 0 {
		var likeRecord likes.Likes
		e.Orm.Model(&likes.Likes{}).Where("tenant_id = ? and bind_id =? and round_id = ?", data.TenantId, data.Id, data.RoundId).Find(&likeRecord)
		model.Likes = likeRecord
	}

	//获取录制任务状态
	var task live.RecordTask
	e.Orm.Model(&live.RecordTask{}).Select("id,task_state").Where("task_id=?", data.TaskId).Find(&task)
	if task.Id > 0 {
		model.BasicInfo.IsRecord = task.TaskState
	} else {
		model.BasicInfo.IsRecord = 2
	}
	return nil
}

func (e *LiveBasic) GetWithTx(tx *gorm.DB, d *dto.LiveBasicGetReq, model *live.LiveBasicWithStream) error {
	var data live.LiveBasic
	streamInfos := make([]live.LiveMonitorRecord, 0, 3)
	var p []live.Personalization

	//获取直播间基本信息
	err := tx.Where("id = ? and is_delete = 2 and tenant_id=?", d.GetId(), d.TenantId).Find(&data).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	if data.Id <= 0 {
		return errors.New("未找到直播间信息")
	}

	model.BasicInfo.LiveBasic = data

	//获取个性化设置
	err = tx.Model(&live.Personalization{}).Where("live_id=?", data.Id).Find(&p).Error
	if err != nil {
		return err
	}
	for _, v := range p {
		if v.Kind == 1 {
			model.BasicInfo.GuidId = v.Id
			model.BasicInfo.EnableGuid = v.IsEnable
		}
		if v.Kind == 2 {
			model.BasicInfo.VirtualNumId = v.Id
			model.BasicInfo.EnableVirtualNum = v.IsEnable
		}
		if v.Kind == 3 {
			model.BasicInfo.IMId = v.Id
			model.BasicInfo.EnableIM = v.IsEnable
		}
		if v.Kind == 4 {
			model.BasicInfo.LikesId = v.Id
			model.BasicInfo.EnableLikes = v.IsEnable
		}

		if v.Kind == 5 {
			model.BasicInfo.CommentId = v.Id
			model.BasicInfo.EnableComment = v.IsEnable
			model.BasicInfo.IsAudit = v.IsAudit
		}

		if v.Kind == 7 {
			model.BasicInfo.CountDownId = v.Id
			model.BasicInfo.EnableCountDown = v.IsEnable
		}

		if v.Kind == 8 {
			model.BasicInfo.ReservationId = v.Id
			model.BasicInfo.EnableReservation = v.IsEnable
		}
	}
	if model.BasicInfo.EnableGuid == 0 {
		model.BasicInfo.EnableGuid = 2
	}

	if model.BasicInfo.EnableVirtualNum == 0 {
		model.BasicInfo.EnableVirtualNum = 2
	}

	if model.BasicInfo.EnableLikes == 0 {
		model.BasicInfo.EnableLikes = 2
	}

	if model.BasicInfo.EnableComment == 0 {
		model.BasicInfo.EnableComment = 2
	}

	if model.BasicInfo.EnableCountDown == 0 {
		model.BasicInfo.EnableCountDown = 2
	}

	if model.BasicInfo.EnableReservation == 0 {
		model.BasicInfo.EnableReservation = 2
	}

	//获取直播流信息
	err = tx.Model(&live.LiveMonitorRecord{}).Where("tenant_id = ? and basic_id =? and is_delete = 2", data.TenantId, data.Id).Order("view_no asc").Find(&streamInfos).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	model.StreamInfos = streamInfos
	if len(streamInfos) > 0 {
		model.StreamInfo = streamInfos[0]
	}

	//获取点赞记录
	if data.RoundId > 0 {
		var likeRecord likes.Likes
		e.Orm.Model(&likes.Likes{}).Where("tenant_id = ? and bind_id =? and round_id = ?", data.TenantId, data.Id, data.RoundId).Find(&likeRecord)
		model.Likes = likeRecord
	}

	//获取录制任务状态
	var task live.RecordTask
	err = tx.Model(&live.RecordTask{}).Select("id,task_state").Where("task_id=?", data.TaskId).Find(&task).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	if task.Id > 0 {
		model.BasicInfo.IsRecord = task.TaskState
	} else {
		model.BasicInfo.IsRecord = 2
	}
	return nil
}

// GetForLive 获取LiveBasic对象
func (e *LiveBasic) GetForLive(d *dto.LiveBasicGetReq, model *live.LiveBasicModelForLive) error {

	err := e.Orm.Model(live.LiveBasic{}).
		Select("live_basic.*,live_monitor_record.live_id,live_monitor_record.hls_url").
		Where("live_basic.id = ? and live_basic.is_delete = 2", d.GetId()).
		Joins("left join live_monitor_record on live_basic.id = live_monitor_record.basic_id").
		Where("live_monitor_record.basic_id =? and live_monitor_record.is_delete = 2", d.Id).
		Find(model).
		Error

	if err != nil {
		return err
	}

	return nil
}

func (e *LiveBasic) GetPersonalization(d *dto.GetPersonalReq) (*live.LiveBasicWithStream, error) {

	stream := live.LiveBasicWithStream{}
	//hk := models.PersonalPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(d.Id)
	//data, err := e.Redis.HGetAll(hk)
	//if err != nil || data == nil || len(data) <= 0 {
	//	p := make([]live.Personalization, 0, 5)
	//	err := e.Orm.Model(live.Personalization{}).Where("live_id =?", d.Id).Find(&p).Error
	//	if err != nil {
	//		return nil, err
	//	}
	//
	//	stream.BasicInfo.Id = d.Id
	//	stream.BasicInfo.EnableIM = 2
	//	stream.BasicInfo.EnableLikes = 2
	//	stream.BasicInfo.EnableGuid = 2
	//	stream.BasicInfo.EnableVirtualNum = 2
	//	stream.BasicInfo.EnableComment = 2
	//	for _, v := range p {
	//		switch v.Kind {
	//		case 1:
	//			stream.BasicInfo.GuidId = v.Id
	//			stream.BasicInfo.EnableGuid = v.IsEnable
	//		case 2:
	//			stream.BasicInfo.VirtualNumId = v.Id
	//			stream.BasicInfo.EnableVirtualNum = v.IsEnable
	//		case 3:
	//			stream.BasicInfo.IMId = v.Id
	//			stream.BasicInfo.EnableIM = v.IsEnable
	//		case 4:
	//			stream.BasicInfo.LikesId = v.Id
	//			stream.BasicInfo.EnableLikes = v.IsEnable
	//		case 5:
	//			stream.BasicInfo.CommentId = v.Id
	//			stream.BasicInfo.EnableComment = v.IsEnable
	//		default:
	//			break
	//		}
	//
	//	}
	//	return &stream, nil
	//}
	//for k, v := range data {
	//	k, _ := strconv.Atoi(k)
	//	v, _ := strconv.Atoi(v)
	//	switch k {
	//	case 1:
	//		stream.BasicInfo.EnableGuid = v
	//	case 2:
	//		stream.BasicInfo.EnableVirtualNum = v
	//	case 3:
	//		stream.BasicInfo.EnableIM = v
	//	case 4:
	//		stream.BasicInfo.EnableLikes = v
	//	case 5:
	//		stream.BasicInfo.EnableComment = v
	//	default:
	//		break
	//	}
	//}

	p := make([]live.Personalization, 0, 5)
	err := e.Orm.Model(live.Personalization{}).Where("live_id =?", d.Id).Find(&p).Error
	if err != nil {
		return nil, err
	}

	stream.BasicInfo.Id = d.Id
	stream.BasicInfo.EnableIM = 2
	stream.BasicInfo.EnableLikes = 2
	stream.BasicInfo.EnableGuid = 2
	stream.BasicInfo.EnableVirtualNum = 2
	stream.BasicInfo.EnableComment = 2
	for _, v := range p {
		switch v.Kind {
		case 1:
			stream.BasicInfo.GuidId = v.Id
			stream.BasicInfo.EnableGuid = v.IsEnable
		case 2:
			stream.BasicInfo.VirtualNumId = v.Id
			stream.BasicInfo.EnableVirtualNum = v.IsEnable
		case 3:
			stream.BasicInfo.IMId = v.Id
			stream.BasicInfo.EnableIM = v.IsEnable
		case 4:
			stream.BasicInfo.LikesId = v.Id
			stream.BasicInfo.EnableLikes = v.IsEnable
		case 5:
			stream.BasicInfo.CommentId = v.Id
			stream.BasicInfo.EnableComment = v.IsEnable
		default:
			break
		}

	}
	return &stream, nil

}

// Insert 创建LiveBasic对象
func (e *LiveBasic) Insert(c *dto.LiveBasicInsertReq) error {
	var err error
	var data live.LiveBasic
	c.Generate(&data)

	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			e.Log.Errorf("CreateLive error:%s \r\n", r)
			tx.Rollback()
			//return
		}
	}()

	if err := tx.Error; err != nil {
		return err
	}

	if len(c.LogUrl) > 0 {
		b := e.IsImageURL(c.LogUrl)
		if !b {
			return errors.New(string(apis.ImageError.Code))
		}
	}
	streamHubService := streamHubService.StreamHubService{}
	streamHubService.Log = e.Log
	vrbmService := vrbmService.VrbmService{}
	vrbmService.Log = e.Log
	vdaService := vdaService.VdaService{}
	vdaService.Log = e.Log

	var count int64
	//获取转推数
	err = tx.Model(&live.LiveBasic{}).Where("tenant_id=? and is_delete=2 and live_type !=2", c.TenantId).Count(&count).Error
	if err != nil {
		e.Log.Errorf("get LiveBasic count  error:%s ", err)
		tx.Rollback()
		return err
	}
	//
	//limitRes := &streamHubDto.DisPatchLimitRes{}
	////获取分发限制数
	//limitRes, err = streamHubService.DispatchLimit(&streamHubDto.StreamHubReq{TenantId: c.TenantId})
	//if err != nil {
	//	e.Log.Errorf("DispatchLimit error:%s ", err)
	//	//if strings.Contains(err.Error(), "error:Unauthorized access") {
	//	//	return err
	//	//} else {
	//	//	limitRes.Count = 0
	//	//}
	//	//tx.Rollback()
	//	//return err
	//}
	//
	//if limitRes != nil && limitRes.Count > 0 && limitRes.Rows[0].Quota.GlobalLive.ParanPullNum <= int(count) {
	//	e.Log.Trace("最大转推数：", limitRes.Rows[0].Quota.GlobalLive.ParanPullNum, " 使用数：", count)
	//	return errors.New(string(apis.MaxPushNumError.Code))
	//}

	//var liveDuration int64
	//ParanPullNum := 0
	//liveNum := 0
	//err, liveDuration, ParanPullNum, liveNum = GetLimitData(vrbmService, c.TenantId)
	//if err != nil {
	//	e.Log.Errorf("GetLimiData error:%s ", err)
	//	tx.Rollback()
	//	return err
	//}
	//e.Log.Trace("最大直播时长：", liveDuration, "最大并发数：", ParanPullNum, "最大直播间数:", liveNum)
	//e.Log.Trace("直播间数：", count)
	//if liveNum > 0 && int(count+1) > liveNum {
	//	tx.Rollback()
	//	return errors.New(string(apis.MaxPushNumError.Code))
	//}

	//创建直播间基本信息 直播间状态设置为预告
	err = tx.Create(&data).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("LiveBasicService Insert error:%s \r\n", err)
		return err
	}

	if c.Scene != 3 {
		c.ViewNames = append(c.ViewNames, c.LiveName)
	}
	if c.RoomType == 2 {
		c.ExpireTime = 10 * 365 * 24 * 3600
	}
	cloudLiveService := cloudLiveService.CloudLive{}
	cloudLiveService.Log = e.Log
	records := make([]live.LiveMonitorRecord, 0, 3)
	for k, v := range c.ViewNames {
		v := v
		//创建直播流
		streamReq := &dto.LiveStreamInsertReq{}
		streamReq.EventName = data.LiveName
		streamReq.TenantId = c.TenantId
		//streamReq.ExpireTime = int64(later.Sub(now).Seconds())
		streamReq.ExpireTime = c.ExpireTime
		streamReq.IMEnable = 0
		streamReq.WebPusherEnable = 1
		streamReq.PullOrPush = ""
		streamReq.AutoRecord = "0"
		streamReq.EventType = "1"
		streamReq.ServiceArea = "cn_mainland"
		if k == 0 {
			streamReq.RecordFileCallbackUrl = ext.ExtConfig.ServiceConfig.VrcmServiceUrl + "/api/v1/live-record/record-file-callback"
		}
		stream, err := e.CreateLiveStream(streamReq)
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("CreateLive error:%s \r\n", err)
			return err
		}

		if c.Delay > 0 {
			err = e.DelayLive(stream.LiveId, c.Delay, c.TenantId)
			if err != nil {
				tx.Rollback()
				e.Log.Errorf("DelayLive error:%s \r\n", err)
				return err
			}
		}

		time.Sleep(time.Second * 1)
		if ext.ExtConfig.ServiceConfig.Deploy == "wangshi" {
			err = cloudLiveService.StopPushLive(dto.StopPushLiveReq{LiveId: stream.LiveId, TenantId: c.TenantId})
			if err != nil {
				tx.Rollback()
				e.Log.Errorf("StopPushLive error:%s \r\n", err)
				return err
			}
		}

		//创建直播监控
		stream.CreateBy = data.CreateBy
		stream.BasicId = data.Id
		var record live.LiveMonitorRecord
		stream.Generate(&record)
		record.StreamType = 1
		record.ViewName = v
		record.ViewNo = k
		records = append(records, record)
	}

	c.Id = data.Id
	if len(records) > 0 {
		err = tx.Model(&live.LiveMonitorRecord{}).Create(&records).Error
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("Insert LiveMonitorRecord  error:%s \r\n", err)
			return err
		}
	}

	//设置直播间状态缓存
	key := c.TenantId + models.Delimiter + strconv.Itoa(data.Id)
	err = e.Redis.Set(key, 1, -1)
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("设置直播间状态缓存失败  error:%s \r\n", err)
		return err
	}
	//
	////创建个性化设置缓存
	//hk := models.PersonalPrefix + models.Delimiter + c.TenantId + models.Delimiter + strconv.Itoa(c.Id)
	//kinds := make(map[string]interface{})
	//for i := 0; i <= 5; i++ {
	//	kinds[strconv.Itoa(i)] = 2
	//}
	//err = e.Redis.HashSet(hk, kinds)
	//if err != nil {
	//	e.Log.Errorf("更新个性化设置缓存失败", err)
	//	tx.Rollback()
	//	return err
	//}
	//e.Redis.Expire(hk, time.Minute*5)

	err = e.EnableOrStopIM(tx, &dto.UpdateIMReq{TenantId: c.TenantId, LiveId: data.Id, IsEnable: 2, ChatType: c.ChatType, CreateIM: c.CreateIM})
	if err != nil {
		e.Log.Errorf("启用或者停用评论失败:", err)
		tx.Rollback()
		return err
	}

	err = e.EnableOrStopLikes(tx, &dto.UpdateLikesReq{TenantId: c.TenantId, LiveId: data.Id, IsEnable: 1})
	if err != nil {
		e.Log.Errorf("启用或者停用评论失败:", err)
		tx.Rollback()
		return err

	}

	err = e.EnableOrStopCountDown(tx, &dto.UpdateCountDownReq{TenantId: c.TenantId, LiveId: data.Id, IsEnable: 1})
	if err != nil {
		e.Log.Errorf("启用或者停用倒计时失败:", err)
		tx.Rollback()
		return err
	}

	tx.Commit()

	//创建直播间一开始需要设置为禁推直播流
	//err = e.EndLive(&dto.StartOrEndLiveReq{TenantId: c.TenantId, BasicId: data.Id, LiveType: 1})
	//if err != nil {
	//	//tx.Rollback()
	//	e.Log.Errorf("结束直播推流错误  error:%s \r\n", err)
	//	return err
	//}

	return nil
}

func GetLimitData(vrbmService vrbmService.VrbmService, TenantId string) (error error, liveDuration int64, ParanPullNum int, liveNum int) {
	res, err := vrbmService.GetOnTimeList(&vrbmDto.OnTimeListReq{TenantId: TenantId, RelatedProduct: "私域直播"})
	if err != nil {
		return err, 0, 0, 0
	}
	if len(res) > 0 {
		for _, v := range res {
			if v.Name == "直播时长" {
				switch v.Uint {
				case "小时":
					value, _ := strconv.Atoi(v.DefaultValue)
					liveDuration += int64(value) * 60 * 60
				case "分钟":

				}
			}

			if v.Name == "并发连接数" {
				switch v.Uint {
				case "人":
					value, _ := strconv.Atoi(v.DefaultValue)
					ParanPullNum += value
				case "分钟":

				}
			}
			if v.Name == "直播间数量" {
				switch v.Uint {
				case "个":
					value, _ := strconv.Atoi(v.DefaultValue)
					liveNum += value

				}
			}
		}
	}
	return nil, liveDuration, ParanPullNum, liveNum
}

// InsertVod 创建LiveBasic对象
func (e *LiveBasic) InsertVod(c *dto.LiveBasicInsertReq) error {
	var err error
	var data live.LiveBasic
	c.Generate(&data)

	data.LiveState = 2
	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			e.Log.Errorf("CreateLive error:%s \r\n", r)
			tx.Rollback()
			//return
		}
	}()
	if err := tx.Error; err != nil {
		return err
	}
	streamHubService := streamHubService.StreamHubService{}
	streamHubService.Log = e.Log

	err = e.Orm.Model(&live.LiveBasic{}).Where("bind_id=?", c.BindId).Find(&data).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("get LiveBasic error:%s \r\n", err)
		return err
	}

	if data.Id > 0 {
		c.Id = data.Id
		tx.Commit()
		return nil
	}

	//创建直播间基本信息 直播间状态设置为预告
	err = tx.Create(&data).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("LiveBasicService Insert error:%s \r\n", err)
		return err
	}

	record := live.LiveMonitorRecord{}
	record.TenantId = data.TenantId
	record.BasicId = data.Id
	record.PullStreamUrl = c.VideoUrl
	record.VideoInfo = c.VideoInfo
	record.IsDelete = 2

	c.Id = data.Id
	err = tx.Model(&live.LiveMonitorRecord{}).Create(&record).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("Insert LiveMonitorRecord  error:%s \r\n", err)
		return err
	}
	tx.Commit()
	return nil
}

// PublishVod  发布点播
func (e *LiveBasic) PublishVod(c *dto.PublishVodLiveReq) error {
	err := e.Orm.Model(&live.LiveBasic{}).Where("id=?", c.BasicId).Update("live_state", c.PublishState).Error
	if err != nil {
		e.Log.Errorf("update PublishVod error:%s \r\n", err)
		return err
	}
	return nil
}

func (e *LiveBasic) Remove(d *dto.LiveBasicDeleteReq) error {
	var data live.LiveBasic
	vrcService := vrcService.VrcService{}
	vrcService.Log = e.Log
	mediaProcService := mediaProcService.MediaProcService{}
	mediaProcService.Log = e.Log
	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			e.Log.Errorf("Service RemoveLiveBasic error:%s \r\n", r)
			tx.Rollback()
		}
	}()

	if err := tx.Error; err != nil {
		return err
	}

	if d.Id > 0 {
		tx.Model(&live.LiveBasic{}).Where("id=? and tenant_id=?", d.Id, d.TenantId).Find(&data)
		tx.First(&data, d.Id)
	} else {
		tx.Model(&live.LiveBasic{}).Where("bind_id=? and tenant_id=?", d.BindId, d.TenantId).Find(&data)
	}

	if data.Id <= 0 {
		tx.Rollback()
		return errors.New("未找到直播间")
	}
	//删除直播间基本信息
	db := tx.Model(&data).Where("id = ? and  tenant_id=?", d.Id, d.TenantId).Update("is_delete", 1)
	if err := db.Error; err != nil {
		e.Log.Errorf("Service RemoveLiveBasic error:%s \r\n", err)
		tx.Rollback()
		return err
	}
	//获取直播流信息
	liveIds := make([]string, 0, 5)
	err := tx.Model(&live.LiveMonitorRecord{}).Select("live_id").Where("basic_id= ?  and tenant_id=?", d.Id, d.TenantId).Find(&liveIds).Error
	if err != nil {
		e.Log.Errorf("Service getLiveMonitorRecord error:%s \r\n", err)
		tx.Rollback()
		return err
	}

	//重启拉流直播
	err = e.StopPullStreamLive(tx, &dto.StopPullStreamLiveReq{TenantId: data.TenantId, BasicId: data.Id})
	if err != nil {
		e.Log.Errorf("StopPullStreamLive error:%s \r\n", err)
		tx.Rollback()
		return err
	}
	//删除直播流信息
	err = tx.Model(&live.LiveMonitorRecord{}).Where("basic_id= ? and is_delete = 2 and tenant_id=?", d.Id, d.TenantId).Update("is_delete", 1).Error
	if err != nil {
		e.Log.Errorf("Service RemoveLiveMonitorRecord error:%s \r\n", err)
		tx.Rollback()
		return err
	}

	//关闭聊天室
	var monitor live.Personalization
	tx.Model(&live.Personalization{}).Where("live_id=? and kind = 3", data.Id).Find(&monitor)
	if monitor.IsEnable == 1 {
		im := imService.IMService{}
		im.Log = e.Log
		err = im.DestroyIM(imDto.IMDestroyReqDto{TenantId: data.TenantId, GroupId: data.GroupId})
		if err != nil {
			e.Log.Errorf("Service DestroyIM error:%s \r\n", err)
			tx.Rollback()
			return err
		}
	}

	//禁用活动场次关系
	err = tx.Model(&subject.EventPaper{}).Where("tenant_id =? and event_id =? and event_type =1", data.TenantId, data.Id).Update("is_enable", 2).Error
	if err != nil {
		e.Log.Errorf("Service UpdateEventPaper error:%s \r\n", err)
		tx.Rollback()
		return err
	}

	//删除点赞缓存
	like := make([]likes.Likes, 0, 10)
	fields := make([]string, 0, 10)
	tx.Model(&likes.Likes{}).Where("bind_id =? and tenant_id=?", data.Id, data.TenantId).Find(&like)
	for _, v := range like {
		field := v.TenantId + models.Delimiter + strconv.Itoa(d.Id) + models.Delimiter + strconv.Itoa(v.BindId) + models.Delimiter + strconv.Itoa(v.RoundId)
		fields = append(fields, field)
	}
	for _, v := range fields {
		err = e.Redis.HashDel(models.Prefix, v)
		if err != nil {
			e.Log.Errorf("Service HashDel error:%s \r\n", err)
			tx.Rollback()
			return err
		}
	}

	//删除直播间状态缓存
	key := data.TenantId + models.Delimiter + strconv.Itoa(data.Id)
	err = e.Redis.Del(key)
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("删除直播间状态缓存失败  error:%s \r\n", err)
		return err
	}

	//删除直播流
	for _, v := range liveIds {
		v := v
		if len(v) > 0 {
			err = e.RemoveLive(&dto.StopLiveReq{TenantId: data.TenantId, LiveId: v})
			if err != nil {
				tx.Rollback()
				e.Log.Errorf("删除直播流失败  error:%s \r\n", err)
				return err
			}
		}
	}

	//获取转推任务
	thirdPushes := make([]live.ThirdPush, 0, 5)
	err = tx.Model(&live.ThirdPush{}).Where("basic_id=?", d.Id).Find(&thirdPushes).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("get ThirdPush  error:%s \r\n", err)
		return err
	}
	streamHubService := streamHubService.StreamHubService{}
	streamHubService.Log = e.Log
	streamHubService.Orm = e.Orm
	for _, v := range thirdPushes {
		v := v
		if len(v.TaskId) > 0 {
			err = streamHubService.RemoveStreamHub(&streamHubDto.StreamHubReq{TenantId: v.TenantId, Id: v.TaskId})
			if err != nil {
				tx.Rollback()
				e.Log.Errorf("删除转推失败  error:%s \r\n", err)
				return err
			}
		}
	}

	err = tx.Model(&live.ThirdPush{}).Where("basic_id=?", d.Id).Delete(&live.ThirdPush{}).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("delete ThirdPush  error:%s \r\n", err)
		return err
	}

	if len(data.EventId) > 0 {
		err = vrcService.DeleteRoom1(&vrcDto.DeleteRoomReq{TenantId: data.TenantId, EventId: data.EventId})
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("DeleteRoom1 error:%s \r\n", err)
			return err
		}
	}

	if data.MergeScreenId > 0 {
		mediaProcService.StopMergeScreenTask(&mediaProcDto.StopMergeScreenReq{Id: data.MergeScreenId})
		mediaProcService.DeleteMergeScreenTask(&mediaProcDto.DeleteMergeScreenReq{Id: data.MergeScreenId})
	}

	tx.Commit()
	return nil
}

// IsExitLiveBasic  判断是否存在LiveBasic对象
func (e *LiveBasic) IsExitLiveBasic(c *dto.LiveBasicReq) bool {

	var basic live.LiveBasic
	var err error
	c.IsDelete = 2

	b := live.LiveBasic{}
	err = e.Orm.Model(&live.LiveBasic{}).Where("id=?", c.Id).Find(&b).Error
	if err != nil {
		return true
	}
	if b.LiveType == 2 {
		return false
	}

	basicWhere := live.LiveBasic{LiveName: c.LiveName, TenantId: c.TenantId, IsDelete: 2}
	if c.Id > 0 {
		err = e.Orm.Where(&basicWhere).Not("id =? or live_type = 2", c.Id).Find(&basic).Error
	} else {
		err = e.Orm.Where(&basicWhere).Find(&basic).Error
	}

	if err != nil {
		return true
	}

	if basic.Id > 0 {
		return true
	}
	return false
}

// Update 修改LiveBasic对象
func (e *LiveBasic) Update(c *dto.LiveBasicUpdateReq) error {
	var err error
	var data = live.LiveBasic{}
	//imService := imService.IMService{}
	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	if err = tx.Error; err != nil {
		return err
	}

	if len(c.LogUrl) > 0 {
		b := e.IsImageURL(c.LogUrl)
		if !b {
			return errors.New(string(apis.ImageError.Code))
		}
	}

	err = tx.Model(&live.LiveBasic{}).Where("id=? and tenant_id=?", c.Id, c.TenantId).Find(&data).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("get LiveBasic:%s ", err)
		return err
	}

	if c.Id > 0 && data.Id < 0 {
		return errors.New("未找到直播间信息")
	}

	//e.Orm.First(&data, c.GetId())
	c.Generate(&data)
	if data.LiveTime > time.Now().Unix() && data.LiveState == 4 {
		data.LiveState = 1
	}
	db := tx.Save(&data)
	if err = db.Error; err != nil {
		tx.Rollback()
		e.Log.Errorf("LiveBasicService Save error:%s \r\n", err)
		return err
	}

	if data.Scene == 3 {
		records := make([]live.LiveMonitorRecord, 0, 3)
		err = tx.Model(&live.LiveMonitorRecord{}).Where("basic_id=?", c.Id).Find(&records).Error
		if err != nil {
			e.Log.Errorf("get LiveMonitorRecord error:%s \r\n", err)
			tx.Rollback()
			return err
		}
		addItems := make([]dto.View, 0, 5)
		updateItems := make([]live.LiveMonitorRecord, 0, 3)
		delItems := make([]live.LiveMonitorRecord, 0, 3)
		recordMap := make(map[int]dto.View)
		for _, v := range c.Views {
			v := v
			if v.Id <= 0 {
				view := dto.View{}
				view.ViewNo = v.ViewNo
				view.ViewName = v.ViewName
				addItems = append(addItems, view)
			} else {
				recordMap[v.Id] = v
			}

		}
		for k, v := range records {
			v := v
			r, ok := recordMap[v.Id]
			if !ok {
				delItems = append(delItems, v)
			} else {
				*(&records[k].ViewName) = r.ViewName
				*(&records[k].ViewNo) = r.ViewNo
				updateItems = append(updateItems, records[k])
			}
		}
		if len(updateItems) > 0 {
			err = tx.Save(&updateItems).Error
			if err != nil {
				tx.Rollback()
				e.Log.Errorf("save LiveMonitorRecord error:%s ", err)
				return err
			}
		}
		if len(delItems) > 0 {
			ids := make([]int, 0, 5)
			for _, v := range delItems {
				err = e.RemoveLive(&dto.StopLiveReq{TenantId: v.TenantId, LiveId: v.LiveId})
				if err != nil {
					tx.Rollback()
					e.Log.Errorf("RemoveLive error:%s ", err)
					return err
				}
				ids = append(ids, v.Id)
			}
			err = tx.Model(&live.LiveMonitorRecord{}).Where("id in ?", ids).Delete(&live.LiveMonitorRecord{}).Error
			if err != nil {
				tx.Rollback()
				e.Log.Errorf("delete LiveMonitorRecord error:%s ", err)
				return err
			}
		}
		if len(addItems) > 0 {
			addRecords := make([]live.LiveMonitorRecord, 0, 3)
			for _, v := range addItems {
				v := v
				//创建直播流
				streamReq := &dto.LiveStreamInsertReq{}
				streamReq.EventName = v.ViewName
				streamReq.TenantId = c.TenantId
				streamReq.ExpireTime = 7 * 24 * 60 * 60
				streamReq.IMEnable = 0
				streamReq.WebPusherEnable = 1
				streamReq.PullOrPush = ""
				streamReq.AutoRecord = "0"
				streamReq.EventType = "1"
				streamReq.ServiceArea = "cn_mainland"
				streamReq.RecordFileCallbackUrl = ext.ExtConfig.ServiceConfig.VrcmServiceUrl + "/api/v1/live-record/record-file-callback"
				stream, err := e.CreateLiveStream(streamReq)
				if err != nil {
					tx.Rollback()
					e.Log.Errorf("CreateLive error:%s \r\n", err)
					return err
				}

				if c.Delay > 0 {
					err = e.DelayLive(stream.LiveId, c.Delay, c.TenantId)
					if err != nil {
						tx.Rollback()
						e.Log.Errorf("DelayLive error:%s \r\n", err)
						return err
					}
				}

				//创建直播监控
				stream.CreateBy = data.CreateBy
				stream.BasicId = data.Id
				var record live.LiveMonitorRecord
				stream.Generate(&record)
				record.StreamType = 1
				record.ViewName = v.ViewName
				record.ViewNo = v.ViewNo
				addRecords = append(addRecords, record)
			}
			if len(addRecords) > 0 {
				err = tx.Model(&live.LiveMonitorRecord{}).Create(&addRecords).Error
				if err != nil {
					tx.Rollback()
					e.Log.Errorf("create LiveMonitorRecord error:%s ", err)
					return err
				}
			}
		}
	}

	if len(c.RecordId) > 0 {
		param := make(map[string]interface{})
		param["file_name"] = c.LiveName
		param["file_img"] = c.LogUrl
		err = tx.Model(&live.RecordList{}).Where("record_id=?", c.RecordId).Updates(&param).Error
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("RecordList Save error:%s \r\n", err)
			return err
		}
	}

	tx.Commit()
	return nil
}

func (e *LiveBasic) SaveCorpId(c *dto.SaveCorpIdReq) error {
	wechatService := wechatService.WechatService{}
	wechatService.Log = e.Log
	wechatService.Redis = e.Redis

	corpIdSecrets := ""
	var wg sync.WaitGroup
	corpIds := strings.Split(c.CorpIds, ";")
	for i := 0; i < len(corpIds); i++ {
		wg.Add(1) // 添加一个等待任务
		go func(wg *sync.WaitGroup, i int) {
			defer wg.Done()
			info, err := wechatService.CorpIdToOpenCorpId(&wechat.ToOpenCorpIdReq{CorpId: corpIds[i]})
			if err != nil {
				e.Log.Errorf("CorpIdToOpenCorpId error:%s \r\n", err)
			}
			if info != nil {
				corpIdSecrets = corpIdSecrets + info.OpenCorpId + ";"
			} else {
				corpIdSecrets = corpIdSecrets + "" + ";"
			}

		}(&wg, i)
	}
	wg.Wait()

	param := make(map[string]interface{})
	param["corp_id"] = c.CorpIds
	param["corp_id_secret"] = strings.Trim(corpIdSecrets, ";")
	param["update_time"] = time.Now().Unix()
	param["corp_agent_id"] = strings.Trim(c.AgentIds, ";")
	err := e.Orm.Model(&live.LiveBasic{}).Where("id=?", c.Id).Updates(&param).Error
	if err != nil {
		e.Log.Errorf("update LiveBasic error:%s \r\n", err)
		return err
	}
	return nil
}

// DressLive 彩排
func (e *LiveBasic) DressLive(d *dto.StartOrEndLiveReq) error {
	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	if err := tx.Error; err != nil {
		return err
	}
	//通过基本信息id获取直播流信息
	var record live.LiveMonitorRecord
	tx.Model(&live.LiveMonitorRecord{}).Where("tenant_id = ? and basic_id = ? and is_delete = 2", d.TenantId, d.BasicId).Find(&record)
	if record.Id <= 0 {
		return errors.New("未找到直播间流信息")
	}
	//if d.DressState == 1 {
	//
	//	//开启直播
	//	params := url.Values{}
	//	urlString := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/cloud_live/"
	//
	//	//拼接请求地址
	//	urlString = urlString + record.LiveId + "/resume"
	//	Url, err := url.Parse(urlString)
	//	if err != nil {
	//		return err
	//	}
	//	params.Set("tenant_id", d.TenantId)
	//	Url.RawQuery = params.Encode()
	//	urlPath := Url.String()
	//	// 获取 request请求
	//	request, err := http.NewRequest("PUT", urlPath, nil)
	//	if err != nil {
	//		tx.Rollback()
	//		e.Log.Errorf("GetHttpSkip Request Error:", err)
	//		return err
	//	}
	//	request.Header.Set("Authorization", "Bearer "+models.SuperToken)
	//request.Header.Set("X-PS-Flag", "")
	//	response, err := client.Do(request)
	//	defer response.Body.Close()
	//	body, err := ioutil.ReadAll(response.Body)
	//	if err != nil {
	//		tx.Rollback()
	//		e.Log.Errorf("读取响应体失败 error:%s", err)
	//		return err
	//	}
	//	result := gjson.Parse(string(body))
	//	if result.Get("code").Int() != http.StatusOK {
	//		tx.Rollback()
	//		e.Log.Errorf("恢复直播失败 error:%s", result.Get("message").String())
	//		return errors.New(result.Get("message").String())
	//	}
	//
	//	err = tx.Model(&live.LiveBasic{}).Where("id = ?", d.BasicId).Update("live_state", d.LiveType).Error
	//	if err != nil {
	//		tx.Rollback()
	//		e.Log.Errorf("更新直播状态失败 error:%s", err)
	//		return err
	//	}
	//} else {
	//	//禁推直播
	//	params := url.Values{}
	//	urlString := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/cloud_live/"
	//	//拼接请求地址
	//	urlString = urlString + record.LiveId + "/forbid"
	//	Url, err := url.Parse(urlString)
	//	if err != nil {
	//		tx.Rollback()
	//		e.Log.Errorf("ParseUrl Request Error:", err)
	//		return err
	//	}
	//	params.Set("tenant_id", d.TenantId)
	//	Url.RawQuery = params.Encode()
	//	urlPath := Url.String()
	//
	//	// 获取 request请求
	//	request, err := http.NewRequest("PUT", urlPath, nil)
	//	if err != nil {
	//		tx.Rollback()
	//		e.Log.Errorf("GetHttpSkip Request Error:", err)
	//		return err
	//	}
	//	request.Header.Set("Authorization", "Bearer "+models.SuperToken)
	//request.Header.Set("X-PS-Flag", "")
	//	response, err := client.Do(request)
	//	defer response.Body.Close()
	//	body, err := ioutil.ReadAll(response.Body)
	//	if err != nil {
	//		tx.Rollback()
	//		e.Log.Errorf("读取响应体失败 error:%s", err)
	//		return err
	//	}
	//	result := gjson.Parse(string(body))
	//	if result.Get("code").Int() != http.StatusOK && result.Get("code").Int() != 170002 {
	//		tx.Rollback()
	//		return errors.New(result.Get("message").String())
	//	}
	//	//更新直播状态
	//	var basic live.LiveBasic
	//	tx.First(&basic, d.BasicId)
	//	err = tx.Model(&live.LiveBasic{}).Where("tenant_id = ? and id = ? and is_delete = 2", d.TenantId, d.BasicId).Update("LiveState", d.LiveType).Error
	//	if err != nil {
	//		tx.Rollback()
	//		e.Log.Errorf("更新直播状态失败 error:%s", err)
	//		return err
	//	}
	//}

	tx.Commit()
	return nil
}

// CreateLiveStream 调用接口创建直播流
func (e *LiveBasic) CreateLiveStream(d *dto.LiveStreamInsertReq) (*dto.LiveMonitorRecordInsertReq, error) {

	res := &dto.LiveMonitorRecordInsertReq{}
	params := url.Values{}
	urlString := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/cloud_live"
	Url, err := url.Parse(urlString)
	if err != nil {
		return nil, err
	}
	params.Set("tenant_id", d.TenantId)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	e.Log.Trace("NgvsaServiceUrl:", urlPath)

	// 参数
	data := make(map[string]interface{})
	data["event_name"] = d.EventName
	data["event_type"] = d.EventType
	data["expire_time"] = d.ExpireTime
	data["app_name"] = d.AppName
	data["service_area"] = d.ServiceArea
	data["auto_record"] = d.AutoRecord
	data["pull_or_push"] = d.PullOrPush
	data["web_pusher_enable"] = d.WebPusherEnable
	data["imEnable"] = d.IMEnable
	data["pull_opull_url"] = d.PullStreamAddress
	data["recordCallbackUrl"] = d.RecordFileCallbackUrl
	data["tag"] = d.Tag
	// Marshal
	e.Log.Trace(data)
	bytesData, _ := json.Marshal(data)
	// 获取 request请求
	request, err := http.NewRequest("POST", urlPath, bytes.NewReader(bytesData))
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	request.Header.Add("Content-Type", "application/json")
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return nil, err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return nil, err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return res, err
	}
	e.Log.Trace(string(body))
	result := gjson.Parse(string(body))
	if result.Get("code").String() != "200" {
		return res, errors.New(result.Get("message").String())
	}
	res.LiveId = result.Get("data").Get("id").String()
	res.TenantId = d.TenantId
	res.ExpireTime = d.ExpireTime
	res.FlvUrl = gjson.Get(result.Get("data").String(), `pull_address.#[format="flv"].url`).String()
	res.HlsUrl = gjson.Get(result.Get("data").String(), `pull_address.#[format="hls"].url`).String()
	res.WebrtcUrl = gjson.Get(result.Get("data").String(), `pull_address.#[format="webrtc"].url`).String()
	res.RtmpUrl = gjson.Get(result.Get("data").String(), `pull_address.#[format="rtmp"].url`).String()
	res.PreviewUrl = gjson.Get(result.Get("data").String(), `pull_address.#[format="preview"].url`).String()
	res.RoomAddress = result.Get("data").Get("live_room").Get("target").String()
	res.RoomNo = result.Get("data").Get("live_room").Get("event").String()
	pushes := result.Get("data").Get("push_address").Array()
	tempAddresses := make([]string, 0, 2)
	for _, v := range pushes {
		tempAddresses = append(tempAddresses, v.String())
	}
	res.PushUrl = strings.Join(tempAddresses, models.Delimiter)

	return res, nil
}

func (e *LiveBasic) DelayLive(liveId string, delayTime int, tenantId string) error {

	params := url.Values{}
	urlString := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/cloud_live"
	urlString = urlString + "/" + liveId + "/delay"
	Url, err := url.Parse(urlString)
	if err != nil {
		return err
	}
	params.Set("tenant_id", tenantId)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	e.Log.Trace("DelayLive:", urlPath)

	data := make(map[string]interface{})
	data["delay_time"] = delayTime
	bytesData, _ := json.Marshal(data)
	// 获取 request请求
	request, err := http.NewRequest("PUT", urlPath, bytes.NewReader(bytesData))
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	request.Header.Add("Content-Type", "application/json")
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return err
	}
	e.Log.Trace(string(body))
	result := gjson.Parse(string(body))
	if result.Get("code").String() != "200" {
		return errors.New(result.Get("message").String())
	}

	return nil
}

// UpdateLiveStreamExpireTime 更新直播流过期时间
func (e *LiveBasic) UpdateLiveStreamExpireTime(d *dto.UpdateLiveStreamExpireTimeReq) error {

	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	if err := tx.Error; err != nil {
		return err
	}
	cloudLiveService := cloudLiveService.CloudLive{}
	cloudLiveService.Log = e.Log

	var basic live.LiveBasic
	tx.First(&basic, d.BasicId)
	if basic.Id <= 0 {
		tx.Rollback()
		return errors.New("未找到直播间")
	}

	records := make([]live.LiveMonitorRecord, 0, 5)
	err := tx.Model(&live.LiveMonitorRecord{}).Where("basic_id=?", d.BasicId).Find(&records).Error
	if err != nil {
		e.Log.Errorf("get LiveMonitorRecord error:%s \r\n", err)
		tx.Rollback()
		return err
	}

	outUrl := ""
	for k, v := range records {
		v := v
		//创建直播流
		streamReq := &dto.LiveStreamInsertReq{}
		streamReq.EventName = basic.LiveName
		streamReq.TenantId = basic.TenantId
		//streamReq.ExpireTime = int64(later.Sub(now).Seconds())
		streamReq.ExpireTime = d.ExpireTime
		streamReq.IMEnable = 0
		streamReq.WebPusherEnable = 1
		streamReq.PullOrPush = ""
		streamReq.AutoRecord = "0"
		streamReq.EventType = "1"
		streamReq.ServiceArea = "cn_mainland"

		if k == 0 {
			streamReq.RecordFileCallbackUrl = ext.ExtConfig.ServiceConfig.VrcmServiceUrl + "/api/v1/live-record/record-file-callback"
		}

		res, err := e.CreateLiveStream(streamReq)
		if err != nil {
			e.Log.Errorf("StartLive error:%s \r\n", err)
			tx.Rollback()
			return err
		}

		param := make(map[string]interface{})
		param["update_time"] = time.Now().Unix()
		param["expire_time"] = d.ExpireTime
		param["flv_url"] = res.FlvUrl
		param["hls_url"] = res.HlsUrl
		param["rtmp_url"] = res.RtmpUrl
		param["view_url"] = res.ViewUrl
		param["push_url"] = res.PushUrl
		param["webrtc_url"] = res.WebrtcUrl
		param["live_id"] = res.LiveId
		param["preview_url"] = res.PreviewUrl
		err = tx.Model(&live.LiveMonitorRecord{}).Where("id=?", v.Id).Updates(&param).Error
		if err != nil {
			e.Log.Errorf("StartLive error:%s \r\n", err)
			tx.Rollback()
			return err
		}
		if len(outUrl) <= 0 {
			arr := strings.Split(res.PushUrl, models.Delimiter)
			if len(arr) > 0 {
				outUrl = arr[0]
			}
		}
		time.Sleep(time.Second * 1)
		err = cloudLiveService.StopPushLive(dto.StopPushLiveReq{LiveId: res.LiveId, TenantId: d.TenantId})
		if err != nil {
			e.Log.Errorf("StopPushLive error:%s \r\n", err)
			tx.Rollback()
			return err
		}
	}

	//重启拉流直播
	var record live.LiveMonitorRecord
	err = tx.Model(&live.LiveMonitorRecord{}).Where("basic_id=? and stream_type=2 and pull_state =1", d.BasicId).Find(&record).Error
	if err != nil {
		e.Log.Errorf("get LiveMonitorRecord error:%s \r\n", err)
		tx.Rollback()
		return err
	}
	if len(record.PullTaskId) > 0 && record.PullState == 1 {
		err = e.StopPullStreamLive(tx, &dto.StopPullStreamLiveReq{TenantId: d.TenantId, BasicId: d.BasicId})
		if err != nil {
			e.Log.Errorf("StopPullStreamLive error:%s \r\n", err)
			tx.Rollback()
			return err
		}
		err = e.StartPullStreamLive(tx, &dto.StartPullStreamLiveReq{TenantId: d.TenantId, BasicId: d.BasicId})
		if err != nil {
			e.Log.Errorf("StartPullStreamLiveReq error:%s \r\n", err)
			tx.Rollback()
			return err
		}
	}

	//获取转推地址
	thirdPushes := make([]live.ThirdPush, 0, 3)
	err = tx.Model(&live.ThirdPush{}).Where("basic_id=?", d.BasicId).Find(&thirdPushes).Error
	if err != nil {
		e.Log.Errorf("get ThirdPush error:%s \r\n", err)
		tx.Rollback()
		return err
	}
	for _, v := range thirdPushes {
		v := v
		if len(v.TaskId) > 0 && v.PushState == 1 {
			err = e.StopPlatform(&dto.StopPlatformReq{Id: v.Id})
			if err != nil {
				e.Log.Errorf("StopPlatform error:%s \r\n", err)
				tx.Rollback()
				return err
			}
			err = e.StartPlatform(&dto.StartPlatformReq{Id: v.Id})
			if err != nil {
				e.Log.Errorf("StartPlatform error:%s \r\n", err)
				tx.Rollback()
				return err
			}
		}
	}

	if basic.MergeScreenId > 0 {
		mediaProcService := mediaProcService.MediaProcService{}
		mediaProcService.Log = e.Log
		err = mediaProcService.UpdateMergeScreenOutUrl(&mediaProcDto.MergeScreenOutUrlUpdateReq{Id: basic.MergeScreenId, OutUrl: outUrl})
		if err != nil {
			e.Log.Errorf("UpdateMergeScreenOutUrl error:%s \r\n", err)
			tx.Rollback()
			return err
		}
	}

	tx.Commit()
	return nil
}

// UpdateLiveStream 更新直播流
func (e *LiveBasic) UpdateLiveStream(d *dto.LiveMonitorRecordInsertReq) error {
	tx := e.Orm.Begin()
	//更新原来的直播流地址为删除状态
	err := tx.Model(&live.LiveMonitorRecord{}).Where("basic_id = ? and is_delete = 2", d.BasicId).Update("is_delete", 1).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("LiveMonitorRecordService update error:%s \r\n", err)
		return err
	}
	//插入新直播流地址
	var data live.LiveMonitorRecord
	d.Generate(&data)
	err = tx.Model(&live.LiveMonitorRecord{}).Create(&data).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("LiveMonitorRecordService Insert error:%s \r\n", err)
		return err
	}
	tx.Commit()
	return nil
}

// StartLive 开启直播
func (e *LiveBasic) StartLive(d *dto.StartOrEndLiveReq) error {

	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			e.Log.Errorf("StartLive error:%s \r\n", r)
			tx.Rollback()
		}
	}()
	if err := tx.Error; err != nil {
		return err
	}

	liveRecord := LiveRecord{}
	liveRecord.Log = e.Log
	liveRecord.Orm = e.Orm

	cloudLiveService := cloudLiveService.CloudLive{}
	cloudLiveService.Log = e.Log

	//获取直播间基本信息
	var basic live.LiveBasic
	tx.First(&basic, d.BasicId)
	if basic.LiveState == 2 {
		tx.Rollback()
		return errors.New(string(apis.StartLiveError.Code))

	}

	vrbmService := vrbmService.VrbmService{}
	vrbmService.Log = e.Log
	var liveDuration int64
	ParanPullNum := 0
	liveNum := 0
	err, liveDuration, ParanPullNum, liveNum := GetLimitData(vrbmService, d.TenantId)
	if err != nil {
		e.Log.Errorf("GetLimiData error:%s ", err)
		tx.Rollback()
		return err
	}
	e.Log.Trace("最大直播时长：", liveDuration, "最大并发数：", ParanPullNum, "最大直播间数:", liveNum)
	now := time.Now().Unix()
	if liveDuration > 0 {
		scheduleRecords := make([]live_schedule.ScheduleRecord, 0, 5)
		err = tx.Model(&live_schedule.ScheduleRecord{}).Where("tenant_id=? and type=6", d.TenantId).Find(&scheduleRecords).Error
		if err != nil {
			e.Log.Errorf("get ScheduleRecord error:%s ", err)
			tx.Rollback()
			return err
		}

		var duration int64
		for _, record := range scheduleRecords {
			if record.EndTime == 0 {
				record.EndTime = now
			}
			duration += record.EndTime - record.StartTime
		}

		e.Log.Trace("直播间耗时：", duration)
		if duration > liveDuration {
			tx.Rollback()
			return errors.New(string(apis.MaxLiveDurationError.Code))
		}
	}

	//设置直播间状态缓存
	key := d.TenantId + models.Delimiter + strconv.Itoa(basic.Id)
	//通过基本信息id获取直播流信息
	records := make([]live.LiveMonitorRecord, 0, 3)
	tx.Model(&live.LiveMonitorRecord{}).Where("tenant_id = ? and basic_id = ? and is_delete = 2", d.TenantId, d.BasicId).Find(&records)
	if len(records) <= 0 {
		tx.Rollback()
		return errors.New("未找到直播流信息")
	}

	//记录直播时长
	scheduleRecord := live_schedule.ScheduleRecord{}
	scheduleRecord.TenantId = d.TenantId
	scheduleRecord.ChannelId = d.BasicId
	scheduleRecord.ChannelTaskId = records[0].LiveId
	scheduleRecord.Type = 6
	scheduleRecord.StartTime = time.Now().Unix()
	scheduleRecord.EndTime = 0
	err = tx.Model(&live_schedule.ScheduleRecord{}).Create(&scheduleRecord).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("Create scheduleRecord error:%s \r\n", err)
		return err
	}

	isRestLive := false
	//开启直播 直播间状态为结束不需要开启直播流
	if basic.LiveState == 4 || (ext.ExtConfig.ServiceConfig.Deploy == "wangshi" && basic.LiveState == 1) {
		for _, record := range records {
			err = cloudLiveService.StartPushLive(dto.StartPushLiveReq{LiveId: record.LiveId, TenantId: d.TenantId})
			if err != nil {
				tx.Rollback()
				e.Log.Errorf("StartPushLive Error:", err)
				return err
			}

			//params := url.Values{}
			//urlString := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/cloud_live/"
			//
			////拼接请求地址
			//urlString = urlString + record.LiveId + "/resume"
			//Url, err := url.Parse(urlString)
			//if err != nil {
			//	return err
			//}
			//params.Set("tenant_id", d.TenantId)
			//Url.RawQuery = params.Encode()
			//urlPath := Url.String()
			//// 获取 request请求
			//request, err := http.NewRequest("PUT", urlPath, nil)
			//if err != nil {
			//	tx.Rollback()
			//	e.Log.Errorf("GetHttpSkip Request Error:", err)
			//	return err
			//}
			//request.Header.Set("Authorization", "Bearer "+models.SuperToken)
			//request.Header.Set("X-PS-Flag", "")
			//response, err := client.Do(request)
			//body, err := ioutil.ReadAll(response.Body)
			//if err != nil {
			//	tx.Rollback()
			//	e.Log.Errorf("读取响应体失败 error:%s", err)
			//	return err
			//}
			//result := gjson.Parse(string(body))
			//if result.Get("code").Int() != http.StatusOK && result.Get("code").Int() != 170002 {
			//	tx.Rollback()
			//	e.Log.Errorf("恢复直播失败 error:%s", result.Get("message").String())
			//	return errors.New(result.Get("message").String())
			//}
			//if result.Get("code").Int() == 170002 {
			//	isRestLive = true
			//}
			//response.Body.Close()

			//如果直播流过期更新过期时间默认+7天
			if record.UpdateTime+record.ExpireTime < time.Now().Unix() || isRestLive {

				//创建直播流
				streamReq := &dto.LiveStreamInsertReq{}
				streamReq.EventName = basic.LiveName
				streamReq.TenantId = basic.TenantId
				streamReq.ExpireTime = 7 * 24 * 60 * 60
				streamReq.IMEnable = 0
				streamReq.WebPusherEnable = 1
				streamReq.PullOrPush = ""
				streamReq.AutoRecord = "0"
				streamReq.EventType = "1"
				//推流或者拉流直播处理
				if record.StreamType == 2 && record.PullState == 1 {
					tx.Rollback()
					return errors.New(string(apis.ResetPullStreamError.Code))
				}
				//else {
				//	streamReq.PullStreamAddress = d.PullStreamAddress
				//	streamReq.EventType = "2"
				//}

				streamReq.ServiceArea = "cn_mainland"
				res, err := e.CreateLiveStream(streamReq)

				if err != nil {
					e.Log.Errorf("创建直播流 error:%s \r\n", err)
					tx.Rollback()
					return err
				}

				param := make(map[string]interface{})
				param["update_time"] = time.Now().Unix()
				param["expire_time"] = 7 * 24 * 60 * 60
				param["flv_url"] = res.FlvUrl
				param["hls_url"] = res.HlsUrl
				param["rtmp_url"] = res.RtmpUrl
				param["view_url"] = res.ViewUrl
				param["push_url"] = res.PushUrl
				param["webrtc_url"] = res.WebrtcUrl
				param["live_id"] = res.LiveId
				err = tx.Model(&live.LiveMonitorRecord{}).Where("tenant_id=? and basic_id=? and is_delete = 2", d.TenantId, d.BasicId).Updates(&param).Error
				if err != nil {
					e.Log.Errorf("StartLive error:%s \r\n", err)
					tx.Rollback()
					return err
				}
			}
		}
	}
	//暂停恢复
	if basic.LiveState == 3 {
		err := tx.Model(&live.LiveBasic{}).Where("tenant_id = ? and id = ? and is_delete = 2", d.TenantId, d.BasicId).Update("live_state", 2).Error
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("更新直播场次失败 error:%s", err)
			return err
		}
		err = e.Redis.Set(key, 2, -1)
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("设置直播间状态缓存失败  error:%s \r\n", err)
			return err
		}
		tx.Commit()
		return nil
	}

	//uuid, _ := uuid.NewV4()
	paper := &subject.Paper{}
	//新增试卷(场次)
	if basic.LiveState == 4 || basic.LiveState == 1 {

		paper.PaperName = basic.LiveName
		paper.StartTime = now
		paper.CreateTime = now
		paper.IsDelete = 2
		paper.PaperType = 1
		err = tx.Model(&subject.Paper{}).Create(paper).Error
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("新增试卷(场次)失败 error:%s", err)
			return err
		}

		//新增点赞的轮次数
		model := &likes.Likes{}
		model.LikeNum = 0
		model.BindId = d.BasicId
		model.TenantId = d.TenantId
		model.RoundId = paper.Id
		model.LikeNum = 0
		model.CreateTime = now
		model.UpdateTime = now
		model.LiveTime = now
		db := tx.Model(&likes.Likes{}).Create(model)
		if db.Error != nil {
			tx.Rollback()
			e.Log.Errorf("新增点赞记录失败 error:%s", err)
			return err
		}
		//新增活动和场次关系
		relation := &subject.EventPaper{}
		relation.TenantId = d.TenantId
		relation.EventId = strconv.Itoa(d.BasicId)
		relation.PaperId = paper.Id
		relation.EventType = 1
		relation.CreateTime = now
		err = tx.Model(&subject.EventPaper{}).Create(relation).Error
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("新增活动场次关系失败 error:%s", err)
			return err
		}

		//更新点赞id
		err = tx.Model(&live.LiveBasic{}).Where("id=?", d.BasicId).Update("likes_id", model.Id).Error
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("更新点赞id失败 error:%s", err)
			return err
		}
		//设置直播间轮次缓存
		roundKey := models.RoundPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(basic.Id)
		err = e.Redis.Set(roundKey, paper.Id, -1)
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("设置直播间状态缓存失败  error:%s \r\n", err)
			return err
		}

		//设置点赞id缓存
		likesKey := models.LikesPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(basic.Id)
		err = e.Redis.Set(likesKey, model.Id, -1)
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("设置点赞id缓存失败  error:%s \r\n", err)
			return err
		}

		//删除点赞缓存
		like := make([]likes.Likes, 0, 10)
		fields := make([]string, 0, 10)
		err = tx.Model(&likes.Likes{}).Where("bind_id =? and tenant_id=? and round_id=?", basic.Id, basic.TenantId, basic.RoundId).Find(&like).Error
		if err != nil {
			e.Log.Errorf("get likes error:%s \r\n", err)
			tx.Rollback()
			return err
		}
		for _, v := range like {
			field := v.TenantId + models.Delimiter + strconv.Itoa(basic.Id) + models.Delimiter + strconv.Itoa(v.BindId) + models.Delimiter + strconv.Itoa(v.RoundId)
			fields = append(fields, field)
		}
		for _, v := range fields {
			err = e.Redis.HashDel(models.Prefix, v)
			if err != nil {
				e.Log.Errorf("Service HashDel error:%s \r\n", err)
				tx.Rollback()
				return err
			}
		}

	}
	//更新直播状态
	//round := int(crc32.ChecksumIEEE([]byte(uuid.String())))
	param := make(map[string]interface{})
	param["live_state"] = 2
	//重制录制文同步件确认
	param["is_confirm"] = 2
	param["update_time"] = now
	param["round_start_time"] = now
	if basic.LiveState == 4 || basic.LiveState == 1 {
		param["round_id"] = paper.Id
	}
	err = tx.Model(&live.LiveBasic{}).Where("tenant_id = ? and id = ? and is_delete = 2", d.TenantId, d.BasicId).Updates(param).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("更新直播场次失败 error:%s", err)
		return err
	}

	err = e.Redis.Set(key, 2, -1)
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("设置直播间状态缓存失败  error:%s \r\n", err)
		return err
	}

	//更新场次为0的抽奖
	basicId := strconv.Itoa(basic.Id)
	err = tx.Model(&draw.DrawBasic{}).Where("bind_id=? and round=0", basicId).Update("round", basic.RoundId).Error
	if err != nil {
		e.Log.Errorf("update DrawBasic  error:%s \r\n", err)
		tx.Rollback()
		return err
	}

	if basic.LiveType != 2 {
		err = liveRecord.StartLiveRecord(tx, &dto.StartRecordReq{TenantId: d.TenantId, BasicId: d.BasicId, RecordName: basic.LiveName})
		if err != nil {
			tx.Rollback()

			e.Log.Errorf("开启录制失败 error:%s", err)
			if err.Error() == "170002" {
				return errors.New("170002")
			}
			return err
		}
	}

	tx.Commit()
	return nil
}

// EndLive 暂停或者结束直播
func (e *LiveBasic) EndLive(d *dto.StartOrEndLiveReq) error {
	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			e.Log.Errorf("EndLive Error:", r)
			tx.Rollback()
		}
	}()
	if err := tx.Error; err != nil {
		return err
	}

	liveRecord := LiveRecord{}
	liveRecord.Log = e.Log
	liveRecord.Orm = e.Orm
	//更新直播状态
	var basic live.LiveBasic
	tx.First(&basic, d.BasicId)
	if basic.LiveTime > time.Now().Unix() && d.LiveType == 4 {
		d.LiveType = 1
	}
	err := tx.Model(&live.LiveBasic{}).Where("tenant_id = ? and id = ? and is_delete = 2", d.TenantId, d.BasicId).Update("LiveState", d.LiveType).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("更新直播状态失败 error:%s", err)
		return err
	}
	if basic.LiveState == 4 {
		return errors.New(string(apis.EndLiveError.Code))
	}

	//暂停不更新结束时间
	if d.LiveType != 3 {
		//更新场次结束时间
		err = tx.Model(&subject.Paper{}).Where("id =? and is_delete = 2", basic.RoundId).Update("end_time", time.Now().Unix()).Error
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("更新场次结束时间失败 error:%s", err)
			return err
		}
	}

	//关闭拉流直播
	var record live.LiveMonitorRecord
	err = tx.Model(&live.LiveMonitorRecord{}).Where("basic_id=? and stream_type=2 and pull_state =1", d.BasicId).Find(&record).Error
	if err != nil {
		e.Log.Errorf("get LiveMonitorRecord error:%s \r\n", err)
		tx.Rollback()
		return err
	}

	var liveMonitorRecord live.LiveMonitorRecord
	err = tx.Model(&live.LiveMonitorRecord{}).Where("basic_id=? and is_delete = 2", d.BasicId).Find(&liveMonitorRecord).Error
	if err != nil {
		e.Log.Errorf("get LiveMonitorRecord error:%s \r\n", err)
		tx.Rollback()
		return err
	}
	cloudLiveService := cloudLiveService.CloudLive{}
	cloudLiveService.Orm = e.Orm
	cloudLiveService.Log = e.Log
	if record.Id > 0 {
		err = cloudLiveService.StopPullLive(dto.StopPullLiveReq{LiveId: record.LiveId, TenantId: d.TenantId})
		if err != nil {
			e.Log.Errorf("StopPullLive error:%s \r\n", err)
			tx.Rollback()
			return err
		}
	}

	//网士停止推流 自动同步录制
	if ext.ExtConfig.ServiceConfig.Deploy == "wangshi" {
		err = cloudLiveService.StopPushLive(dto.StopPushLiveReq{LiveId: liveMonitorRecord.LiveId, TenantId: d.TenantId})
		if err != nil {
			e.Log.Errorf("StopPushLive error:%s \r\n", err)
			tx.Rollback()
			return err
		}

		//自动同步录制
		err = e.ConfirmRecord(tx, &dto.ConfirmRecord{IsConfirm: 1, Id: d.BasicId})
		if err != nil {
			e.Log.Errorf("ConfirmRecord error:%s \r\n", err)
			tx.Rollback()
			return err
		}
	}

	//设置直播间状态缓存
	key := d.TenantId + models.Delimiter + strconv.Itoa(basic.Id)
	err = e.Redis.Set(key, d.LiveType, -1)
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("设置直播间状态缓存失败  error:%s \r\n", err)
		return err
	}

	//更新审核任务记录结束时间
	param := make(map[string]interface{})
	param["end_time"] = time.Now().Unix()
	err = tx.Model(live_schedule.ScheduleRecord{}).Where("channel_id = ? and end_time = 0 and type =6", basic.Id).Updates(&param).Error
	if err != nil {
		e.Log.Errorf("Updates ScheduleRecord error:%s \r\n", err)
		tx.Rollback()
		return err
	}

	tx.Commit()
	return nil
}

// GetToken 获取token
func (e *LiveBasic) GetToken(d *dto.GetTokenReq) (string, error) {

	params := url.Values{}
	urlString := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/authentication"
	Url, err := url.Parse(urlString)
	if err != nil {
		e.Log.Errorf("ParseUrl Request Error:", err)
		return "", err
	}
	params.Set("tenant_id", d.TenantId)
	params.Set("apikey", secretKey)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	// 获取 request请求
	request, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return "", err
	}
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	response, err := client.Do(request)
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return "", err
	}
	result := gjson.Parse(string(body))
	if result.Get("code").Int() != http.StatusOK {
		return "", errors.New(result.Get("message").String())
	}

	fmt.Println(string(body))
	return "", nil
}

func (e *LiveBasic) UpdateBasicInfo(d *dto.UpdateBasicInfoReq) error {
	param := make(map[string]interface{})
	param["live_name"] = d.LiveName
	param["video_list_name"] = d.VideoListName
	param["desc"] = d.Desc
	param["update_by"] = d.UpdateBy
	param["update_time"] = time.Now().Unix()
	err := e.Orm.Model(&live.LiveBasic{}).Where("id =?", d.Id).Updates(param).Error
	if err != nil {
		return err
	}
	return nil
}

func (e *LiveBasic) SaveGuidePage(d *dto.UpdateGuidePageReq) error {

	var guide live.Personalization
	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	if err := tx.Error; err != nil {
		return err
	}

	if len(d.GuideFace) > 0 {
		b := e.IsImageURL(d.GuideFace)
		if !b {
			return errors.New(string(apis.ImageError.Code))
		}
	}

	if len(d.GuideLogo) > 0 {
		b := e.IsImageURL(d.GuideLogo)
		if !b {
			return errors.New(string(apis.ImageError.Code))
		}
	}

	if len(d.GuideBack) > 0 {
		b := e.IsImageURL(d.GuideBack)
		if !b {
			return errors.New(string(apis.ImageError.Code))
		}
	}

	now := time.Now().Unix()
	param := make(map[string]interface{})
	if len(d.LiveName) > 0 {
		param["live_name"] = d.LiveName
	}
	param["guide_face"] = d.GuideFace
	param["guide_back"] = d.GuideBack
	param["guide_logo"] = d.GuideLogo
	param["update_by"] = d.UpdateBy
	param["update_time"] = now
	err := tx.Model(&live.LiveBasic{}).Where("id=?", d.LiveId).Updates(param).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	tx.First(&guide, d.Id)
	guide.Kind = 1
	guide.IsEnable = d.IsEnable
	guide.LiveId = d.LiveId
	if d.Id > 0 {
		guide.Model = common.Model{Id: d.Id}
		guide.UpdateBy = d.UpdateBy
		guide.UpdateTime = now
	} else {
		guide.CreateBy = d.CreateBy
		guide.CreateTime = now
		guide.UpdateTime = now
	}
	err = tx.Model(&guide).Save(&guide).Error
	if err != nil {
		e.Log.Errorf("更新引导页失败", err)
		tx.Rollback()
		return err
	}
	hk := models.PersonalPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(d.LiveId)
	m := make(map[string]interface{})
	m["1"] = d.IsEnable
	err = e.Redis.HashSet(hk, m)
	if err != nil {
		e.Log.Errorf("更新引导页缓存失败", err)
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

func (e *LiveBasic) EnableOrStopIM(tx *gorm.DB, d *dto.UpdateIMReq) error {

	var person live.Personalization
	var liveInfo live.LiveBasic
	imService := &imService.IMService{}
	imService.Log = e.Log
	//tx := e.Orm.Begin()
	//defer func() {
	//	if r := recover(); r != nil {
	//		tx.Rollback()
	//	}
	//}()
	//if err := tx.Error; err != nil {
	//	return err
	//}

	err := tx.Model(&live.Personalization{}).Where("id=?", d.Id).Find(&person).Error
	if err != nil {
		tx.Rollback()
		return errors.New(fmt.Sprintf("获取直播间详情失败，\r\n失败信息 %s", err.Error()))
	}
	if person.LiveId != d.LiveId && person.Id > 0 {
		return errors.New("未找到直播间信息")
	}
	dto := &dto.LiveBasicGetReq{Id: d.LiveId, TenantId: d.TenantId}
	basicWithStream := &live.LiveBasicWithStream{}

	err = e.GetWithTx(tx, dto, basicWithStream)
	if err != nil {
		tx.Rollback()
		return errors.New(fmt.Sprintf("获取直播间详情失败，\r\n失败信息 %s", err.Error()))
	}

	if basicWithStream.BasicInfo.Id <= 0 {
		return errors.New("未找到直播间信息")
	}

	if d.IsEnable == 1 && basicWithStream.BasicInfo.EnableIM != 1 && d.ChatType == "im" {
		//创建聊天室
		im, err := imService.CreateIM(imDto.IMCreateReqDto{Name: d.CreateIM.Name, TenantId: d.CreateIM.TenantId, GroupId: d.CreateIM.GroupId, RoomType: d.CreateIM.RoomType, Notification: d.CreateIM.Notification, ApplyJoinOption: d.CreateIM.ApplyJoinOption})
		if err != nil {
			tx.Rollback()
			return errors.New(fmt.Sprintf("创建CreateIM失败，\r\n失败信息 %s", err.Error()))
		}
		liveInfo.GroupId = im.GroupId

		infos, err := imService.GetGroupInfo(imDto.GetGroupInfoReqDto{TenantId: d.TenantId, GroupIds: []string{d.CreateIM.GroupId}})
		if err != nil {
			return errors.New(fmt.Sprintf("获取IM失败，\r\n失败信息 %s", err.Error()))
		}
		if len(*infos) > 0 {
			err = tx.Model(&live.LiveBasic{}).Where("id = ?", d.LiveId).Update("app_id", (*infos)[0].Appid).Error
			if err != nil {
				tx.Rollback()
				return err
			}

		}
	}

	if d.IsEnable == 2 && basicWithStream.BasicInfo.EnableIM == 1 {
		//摧毁聊天室
		if len(basicWithStream.BasicInfo.GroupId) > 0 {
			err = imService.DestroyIM(imDto.IMDestroyReqDto{TenantId: d.TenantId, GroupId: basicWithStream.BasicInfo.GroupId})
			if err != nil {
				tx.Rollback()
				return errors.New(fmt.Sprintf("DestroyIM失败，\r\n失败信息 %s", err.Error()))
			}
			liveInfo.GroupId = basicWithStream.BasicInfo.GroupId
		}

	}

	if len(liveInfo.GroupId) <= 0 {
		liveInfo.GroupId = basicWithStream.BasicInfo.GroupId
	}

	key := models.GroupPrefix + models.Delimiter + liveInfo.TenantId + models.Delimiter + strconv.Itoa(liveInfo.Id)
	err = e.Redis.Set(key, liveInfo.GroupId, -1)
	if err != nil {
		tx.Rollback()
		return errors.New(fmt.Sprintf("设置群组id缓存失败，\r\n失败信息 %s", err.Error()))
	}
	now := time.Now().Unix()
	param := make(map[string]interface{})
	param["group_id"] = liveInfo.GroupId
	if len(d.CreateBy) > 0 {
		param["update_by"] = d.CreateBy
	} else {
		param["update_by"] = d.UpdateBy
	}
	param["update_time"] = now
	err = tx.Model(&live.LiveBasic{}).Where("id = ?", d.LiveId).Updates(param).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	tx.First(&person, d.Id)
	person.Kind = 3
	person.IsEnable = d.IsEnable
	person.LiveId = d.LiveId
	if d.Id > 0 {
		person.Model = common.Model{Id: d.Id}
		person.UpdateBy = d.UpdateBy
		person.UpdateTime = now
	} else {
		person.CreateBy = d.CreateBy
		person.CreateTime = now
		person.UpdateTime = now
	}
	err = tx.Model(&person).Save(&person).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	m := make(map[string]interface{})
	m["3"] = d.IsEnable
	hk := models.PersonalPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(d.LiveId)
	err = e.Redis.HashSet(hk, m)
	if err != nil {
		e.Log.Errorf("更新引导页缓存失败", err)
		tx.Rollback()
		return err
	}
	err = e.Redis.Expire(hk, time.Minute*30)
	if err != nil {
		e.Log.Errorf("更新引导页缓存失败", err)
		tx.Rollback()
		return err
	}
	//tx.Commit()
	return nil
}

func (e *LiveBasic) SaveVirtualNum(d *dto.UpdateVirtualNumReq) error {

	var person live.Personalization
	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	if err := tx.Error; err != nil {
		return err
	}

	now := time.Now().Unix()
	param := make(map[string]interface{})
	param["basic_num"] = d.BasicNum
	param["multiple"] = d.Multiple
	if len(d.CreateBy) > 0 {
		param["update_by"] = d.CreateBy
	} else {
		param["update_by"] = d.UpdateBy
	}

	param["update_time"] = now
	err := tx.Model(&live.LiveBasic{}).Where("id = ?", d.LiveId).Updates(param).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	tx.First(&person, d.Id)
	person.Kind = 2
	person.IsEnable = d.IsEnable
	person.LiveId = d.LiveId
	if d.Id > 0 {
		person.Model = common.Model{Id: d.Id}
		person.UpdateBy = d.UpdateBy
		person.UpdateTime = now
	} else {
		person.CreateBy = d.CreateBy
		person.CreateTime = now
		person.UpdateTime = now
	}
	err = tx.Model(&person).Save(&person).Error
	if err != nil {
		tx.Rollback()
		return err
	}

	m := make(map[string]interface{})
	m["2"] = d.IsEnable
	hk := models.PersonalPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(d.LiveId)
	err = e.Redis.HashSet(hk, m)
	if err != nil {
		e.Log.Errorf("更新虚拟人数缓存失败", err)
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

func (e *LiveBasic) EnableOrStopLikes(tx *gorm.DB, d *dto.UpdateLikesReq) error {

	var person live.Personalization

	//tx := e.Orm.Begin()
	//defer func() {
	//	if r := recover(); r != nil {
	//		tx.Rollback()
	//	}
	//}()
	if err := tx.Error; err != nil {
		return err
	}
	now := time.Now().Unix()

	err := tx.Model(&live.Personalization{}).Where("id=?", d.Id).Find(&person).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	if person.Id <= 0 && d.Id > 0 {
		return errors.New("未找到点赞信息")
	}

	tx.First(&person, d.Id)
	person.Kind = 4
	person.IsEnable = d.IsEnable
	person.LiveId = d.LiveId
	if d.Id > 0 {
		person.Model = common.Model{Id: d.Id}
		person.UpdateBy = d.UpdateBy
		person.UpdateTime = now
	} else {
		person.CreateBy = d.CreateBy
		person.CreateTime = now
		person.UpdateTime = now
	}
	err = tx.Model(&person).Save(&person).Error
	if err != nil {
		tx.Rollback()
		return err
	}

	m := make(map[string]interface{})
	m["4"] = d.IsEnable
	hk := models.PersonalPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(d.LiveId)
	err = e.Redis.HashSet(hk, m)
	if err != nil {
		e.Log.Errorf("更新点赞缓存失败", err)
		tx.Rollback()
		return err
	}
	//tx.Commit()
	return nil
}

func (e *LiveBasic) EnableOrStopComment(tx *gorm.DB, d *dto.UpdateCommentReq) error {

	var person live.Personalization

	//tx := e.Orm.Begin()
	//defer func() {
	//	if r := recover(); r != nil {
	//		tx.Rollback()
	//	}
	//}()
	//if err := tx.Error; err != nil {
	//	return err
	//}
	now := time.Now().Unix()
	tx.First(&person, d.Id)
	person.Kind = 5
	person.IsEnable = d.IsEnable
	person.LiveId = d.LiveId
	person.IsAudit = d.IsAudit
	if d.Id > 0 {
		person.Model = common.Model{Id: d.Id}
		person.UpdateBy = d.UpdateBy
		person.UpdateTime = now
	} else {
		person.CreateBy = d.CreateBy
		person.CreateTime = now
		person.UpdateTime = now
	}
	err := tx.Model(&person).Save(&person).Error
	if err != nil {
		tx.Rollback()
		return err
	}

	m := make(map[string]interface{})
	m["5"] = d.IsEnable
	hk := models.PersonalPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(d.LiveId)
	err = e.Redis.HashSet(hk, m)
	if err != nil {
		e.Log.Errorf("更新评论缓存失败", err)
		tx.Rollback()
		return err
	}
	//tx.Commit()
	return nil
}

func (e *LiveBasic) EnableOrStopCountDown(tx *gorm.DB, d *dto.UpdateCountDownReq) error {

	var person live.Personalization

	//tx := e.Orm.Begin()
	//defer func() {
	//	if r := recover(); r != nil {
	//		tx.Rollback()
	//	}
	//}()
	//if err := tx.Error; err != nil {
	//	return err
	//}
	now := time.Now().Unix()
	tx.First(&person, d.Id)
	person.Kind = 7
	person.IsEnable = d.IsEnable
	person.LiveId = d.LiveId
	if d.Id > 0 {
		person.Model = common.Model{Id: d.Id}
		person.UpdateBy = d.UpdateBy
		person.UpdateTime = now
	} else {
		person.CreateBy = d.CreateBy
		person.CreateTime = now
		person.UpdateTime = now
	}
	err := tx.Model(&person).Save(&person).Error
	if err != nil {
		tx.Rollback()
		return err
	}

	m := make(map[string]interface{})
	m["7"] = d.IsEnable
	hk := models.PersonalPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(d.LiveId)
	err = e.Redis.HashSet(hk, m)
	if err != nil {
		e.Log.Errorf("更新倒计时失败", err)
		tx.Rollback()
		return err
	}
	//tx.Commit()
	return nil
}

func (e *LiveBasic) EnableOrStopReservation(d *dto.UpdateReservationReq) error {

	var person live.Personalization

	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	if err := tx.Error; err != nil {
		return err
	}
	now := time.Now().Unix()
	tx.First(&person, d.Id)
	person.Kind = 8
	person.IsEnable = d.IsEnable
	person.LiveId = d.LiveId
	if d.Id > 0 {
		person.Model = common.Model{Id: d.Id}
		person.UpdateBy = d.UpdateBy
		person.UpdateTime = now
	} else {
		person.CreateBy = d.CreateBy
		person.CreateTime = now
		person.UpdateTime = now
	}
	err := tx.Model(&person).Save(&person).Error
	if err != nil {
		tx.Rollback()
		return err
	}

	m := make(map[string]interface{})
	m["8"] = d.IsEnable
	hk := models.PersonalPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(d.LiveId)
	err = e.Redis.HashSet(hk, m)
	if err != nil {
		e.Log.Errorf("更新预约观看失败", err)
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

// SavePullStreamAddress 保存拉流地址
func (e *LiveBasic) SavePullStreamAddress(d *dto.PullStreamLiveReq) error {

	var monitor live.LiveMonitorRecord
	e.Orm.Model(&live.LiveMonitorRecord{}).Where("tenant_id =? and  basic_id=?", d.TenantId, d.BasicId).Find(&monitor)

	now := time.Now().Unix()
	if monitor.Id > 0 {
		monitor.UpdateBy = d.UpdateBy
		monitor.UpdateTime = now
	} else {
		monitor.CreateBy = d.CreateBy
		monitor.CreateTime = now
		monitor.UpdateTime = now
		monitor.TenantId = d.TenantId
		monitor.BasicId = d.BasicId
	}
	monitor.PullStreamUrl = strings.Join(d.PullStreamAddress, "^")
	monitor.StreamType = 2
	monitor.PullState = 2
	err := e.Orm.Model(&monitor).Save(&monitor).Error
	if err != nil {
		e.Log.Errorf("SavePullStreamAddress error:%s \r\n", err)
		return err
	}
	return nil
}

// StartPullStreamLive 开启拉流直播
func (e *LiveBasic) StartPullStreamLive(tx *gorm.DB, c *dto.StartPullStreamLiveReq) error {
	cloudLiveService := cloudLiveService.CloudLive{}
	cloudLiveService.Orm = e.Orm
	cloudLiveService.Log = e.Log
	//通过基本信息id获取直播流信息
	var record live.LiveMonitorRecord
	err := tx.Model(&live.LiveMonitorRecord{}).Where("tenant_id = ? and basic_id = ? and is_delete = 2 and stream_type=2", c.TenantId, c.BasicId).Find(&record).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("get LiveMonitorRecord error:%s", err)
		return err
	}
	source := dto.Source{}
	urls := strings.Split(record.PullStreamUrl, "^")
	for k, v := range urls {
		v := v
		if k == 0 {
			source.Main = v
		} else {
			source.Backup = v
		}
	}

	pushUrl := ""
	pushArr := strings.Split(record.PushUrl, models.Delimiter)
	if len(pushArr) > 0 {
		pushUrl = pushArr[0]
	}
	taskId, err := cloudLiveService.StartPullLive(dto.StartPullLiveReq{LiveId: record.LiveId, TenantId: c.TenantId, Source: source, Type: "live", PushUrl: pushUrl})
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("StartPullLive error:%s", err)
		return err
	}
	param := make(map[string]interface{})
	param["pull_state"] = 1
	param["pull_task_id"] = taskId
	err = tx.Model(&live.LiveMonitorRecord{}).Where("basic_id=? and stream_type=2", c.BasicId).Updates(&param).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("update LiveMonitorRecord error:%s", err)
		return err
	}
	//tx.Commit()
	return nil
}

// StopPullStreamLive 停止拉流直播
func (e *LiveBasic) StopPullStreamLive(tx *gorm.DB, c *dto.StopPullStreamLiveReq) error {
	cloudLiveService := cloudLiveService.CloudLive{}
	cloudLiveService.Orm = e.Orm
	cloudLiveService.Log = e.Log
	//通过基本信息id获取直播流信息
	var record live.LiveMonitorRecord
	err := tx.Model(&live.LiveMonitorRecord{}).Where("tenant_id = ? and basic_id = ? and is_delete = 2 and stream_type=2", c.TenantId, c.BasicId).Find(&record).Error
	if err != nil {
		e.Log.Errorf("get LiveMonitorRecord error:%s", err)
		tx.Rollback()
		return err
	}
	err = cloudLiveService.StopPullLive(dto.StopPullLiveReq{LiveId: record.LiveId, TenantId: c.TenantId, Id: record.PullTaskId})
	if err != nil {
		e.Log.Errorf("StopPullLive error:%s", err)
		tx.Rollback()
		return err
	}
	err = tx.Model(&live.LiveMonitorRecord{}).Where("basic_id=? and stream_type=2", c.BasicId).Update("pull_state", 2).Error
	if err != nil {
		e.Log.Errorf("update LiveMonitorRecord error:%s", err)
		tx.Rollback()
		return err
	}
	//tx.Commit()
	return nil
}

func (e *LiveBasic) GetLiveState(d *dto.GetLiveStateReq) (dto.GetLiveStateRes, error) {
	var res dto.GetLiveStateRes
	key := d.TenantId + models.Delimiter + strconv.Itoa(d.Id)
	roundKey := models.RoundPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(d.Id)
	likesKey := models.LikesPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(d.Id)
	groupKey := models.GroupPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(d.Id)
	drawKey := models.DrawPrefix + models.Delimiter + d.TenantId + models.Delimiter + strconv.Itoa(d.Id)
	state, _ := e.Redis.Get(key)
	round, _ := e.Redis.Get(roundKey)
	likes, _ := e.Redis.Get(likesKey)
	groupId, _ := e.Redis.Get(groupKey)
	drawId, _ := e.Redis.Get(drawKey)

	if state == "" || round == "" || likes == "" || groupId == "" || drawId == "" {
		var basic live.LiveBasic
		e.Orm.First(&basic, d.Id)
		if basic.Id > 0 {
			e.Redis.Set(key, basic.LiveState, -1)
			e.Redis.Set(roundKey, basic.RoundId, -1)
			e.Redis.Set(likesKey, basic.LikesId, -1)
			e.Redis.Set(groupKey, basic.GroupId, -1)
			e.Redis.Set(drawKey, basic.DrawId, -1)
		}
		res.LiveState = strconv.Itoa(basic.LiveState)
		res.Round = strconv.Itoa(basic.RoundId)
		res.LikesId = strconv.Itoa(basic.LikesId)
		res.GroupId = basic.GroupId
		res.DrawId = basic.DrawId
		return res, nil
	}
	res.LiveState = state
	res.Round = round
	res.LikesId = likes
	res.GroupId = groupId
	res.DrawId = drawId
	return res, nil
}

// ClosePullStreamLive 关闭拉流直播
func (e *LiveBasic) ClosePullStreamLive(c *dto.PullStreamLiveReq) error {
	var err error
	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	if err := tx.Error; err != nil {
		e.Log.Errorf("PullStreamLive error:%s \r\n", err)
		return err
	}

	//通过基本信息id获取直播流信息
	var record live.LiveMonitorRecord
	tx.Model(&live.LiveMonitorRecord{}).Where("tenant_id = ? and basic_id = ? and is_delete = 2", c.TenantId, c.BasicId).Find(&record)
	if record.Id <= 0 {
		return errors.New("未找到直播流信息")
	}

	//更新原直播流为不可用
	param := make(map[string]interface{})
	param["update_by"] = c.UpdateBy
	param["update_time"] = time.Now().Unix()
	param["is_delete"] = 2
	err = tx.Model(&live.LiveMonitorRecord{}).Where(" tenant_id =? and  basic_id=? and stream_type = 1", c.TenantId, c.BasicId).Updates(param).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("UpdateLiveMonitorRecord error:%s \r\n", err)
		return err
	}
	//更新拉流地址关闭
	param["is_delete"] = 1
	err = tx.Model(&live.LiveMonitorRecord{}).Where(" tenant_id =? and  basic_id=? and stream_type = 2", c.TenantId, c.BasicId).Updates(param).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("UpdateLiveMonitorRecord error:%s \r\n", err)
		return err
	}

	tx.Commit()

	return nil
}

func (e *LiveBasic) DeleteLive(d *dto.DeleteLiveReq) error {

	params := url.Values{}
	urlString := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/cloud_live/"
	//拼接请求地址
	urlString = urlString + d.LiveId
	Url, err := url.Parse(urlString)
	if err != nil {
		e.Log.Errorf("ParseUrl Request Error:", err)
		return err
	}
	params.Set("tenant_id", d.TenantId)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()

	// 获取 request请求
	request, err := http.NewRequest("DELETE", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return err
	}
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	response, err := client.Do(request)
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return err
	}
	fmt.Println(string(body))
	result := gjson.Parse(string(body))
	if result.Get("code").Int() != http.StatusOK && result.Get("code").Int() != 170002 {
		return errors.New(result.Get("message").String())
	}
	return nil
}

func (e *LiveBasic) StopLive(d *dto.StopLiveReq) error {
	params := url.Values{}
	urlString := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/cloud_live/"
	//拼接请求地址
	urlString = urlString + d.LiveId + "/forbid"
	Url, err := url.Parse(urlString)
	if err != nil {
		e.Log.Errorf("ParseUrl Request Error:", err)
		return err
	}
	params.Set("tenant_id", d.TenantId)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()

	// 获取 request请求
	request, err := http.NewRequest("PUT", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return err
	}
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	response, err := client.Do(request)
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return err
	}
	result := gjson.Parse(string(body))
	if result.Get("code").Int() != http.StatusOK && result.Get("code").Int() != 170002 {
		return errors.New(result.Get("message").String())
	}
	return nil

}
func (e *LiveBasic) SavePortal(d *dto.SavePortal) error {

	if len(d.PortalFaceUrl) > 0 {
		b := e.IsImageURL(d.PortalFaceUrl)
		if !b {
			return errors.New(string(apis.ImageError.Code))
		}
	}

	if len(d.PortalLogo) > 0 {
		b := e.IsImageURL(d.PortalLogo)
		if !b {
			return errors.New(string(apis.ImageError.Code))
		}
	}

	portal := live.Portal{}
	if d.Id > 0 {
		err := e.Orm.Model(&live.Portal{}).Where("id=? and tenant_id=?", d.Id, d.TenantId).Find(&portal).Error
		if err != nil {
			e.Log.Errorf("get Portal error:%s \r\n", err)
			return err
		}
		if portal.Id <= 0 {
			return errors.New("门户信息不存在")
		}
	}

	now := time.Now().Unix()
	portal.Id = d.Id
	portal.TenantId = d.TenantId
	portal.PortalName = d.PortalName
	portal.PortalDesc = d.PortalDesc
	portal.PortalLogo = d.PortalLogo
	portal.PortalFaceUrl = d.PortalFaceUrl
	portal.CreateTime = now
	portal.UpdateTime = now
	err := e.Orm.Save(&portal).Error
	if err != nil {
		e.Log.Errorf("save Portal error:%s \r\n", err)
		return err
	}
	return nil
}

func (e *LiveBasic) GetPortal(d *dto.GetPortal) (*live.Portal, error) {
	portal := live.Portal{}
	err := e.Orm.Model(&live.Portal{}).Where("tenant_id=?", d.TenantId).Find(&portal).Error
	if err != nil {
		e.Log.Errorf("get Portal error:%s \r\n", err)
		return nil, err
	}
	urlString := ext.ExtConfig.ServiceConfig.WebClientServiceUrl + "/gateway?"
	params := url.Values{}
	id := strconv.Itoa(portal.Id)
	params.Set("id", id)
	params.Set("tenant_id", portal.TenantId)
	urlString = urlString + url.QueryEscape(params.Encode())
	portal.PortalAddress = urlString
	return &portal, nil
}

func (e *LiveBasic) GetPortalInfo(d *dto.GetPortalInfo) (*live.PortalModel, error) {
	model := live.PortalModel{}
	//获取门户
	portal := live.Portal{}
	err := e.Orm.Model(&live.Portal{}).Where("tenant_id=?", d.TenantId).Find(&portal).Error
	if err != nil {
		e.Log.Errorf("get Portal error:%s \r\n", err)
		return nil, err
	}
	//获取直播间
	basicIds := make([]int, 0, 5)
	err = e.Orm.Model(&live.LiveBasic{}).Select("id").Where("tenant_id=? and is_delete=2", d.TenantId).Find(&basicIds).Error
	if err != nil {
		e.Log.Errorf("get LiveBasic error:%s \r\n", err)
		return nil, err
	}
	//获取点赞数
	var totalLikeNum sql.NullInt64
	if len(basicIds) > 0 {
		err = e.Orm.Model(&likes.Likes{}).
			Select("sum(like_num) as total_like_num").
			Where("bind_id in ?", basicIds).
			Scan(&totalLikeNum).
			Error
		if err != nil {
			e.Log.Errorf("get Likes error:%s \r\n", err)
			return nil, err
		}
	}

	liveNum := len(basicIds)
	model.Portal = portal
	model.TotalLikeNum = totalLikeNum.Int64
	model.LiveNum = liveNum
	urlString := ext.ExtConfig.ServiceConfig.WebClientServiceUrl + "/gateway?"
	params := url.Values{}
	id := strconv.Itoa(portal.Id)
	params.Set("id", id)
	params.Set("tenant_id", portal.TenantId)
	urlString = urlString + url.QueryEscape(params.Encode())
	model.PortalAddress = urlString
	return &model, nil
}

func (e *LiveBasic) ConfirmRecord(tx *gorm.DB, d *dto.ConfirmRecord) error {

	param := make(map[string]interface{})
	param["update_time"] = time.Now().Unix()
	param["is_confirm"] = d.IsConfirm
	err := tx.Model(&live.LiveBasic{}).Where("id=?", d.Id).Updates(&param).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("update LiveBasic:%s", err)
		return err
	}
	var basic live.LiveBasic
	err = tx.Model(&live.LiveBasic{}).Where("id=?", d.Id).Find(&basic).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("get LiveBasic:%s", err)
		return err
	}
	param1 := make(map[string]interface{})
	param1["update_time"] = time.Now().Unix()
	param1["is_confirm"] = d.IsConfirm
	err = tx.Model(&live.RecordListView{}).Where("task_id=?", basic.TaskId).Updates(&param1).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("update RecordListView:%s", err)
		return err
	}

	if d.IsConfirm == 1 {
		var count int64
		err = e.Orm.Model(&live.RecordListView{}).Where("basic_id =?", basic.Id).Count(&count).Error
		if err != nil {
			e.Log.Errorf("RecordListViewService getCount error:%s \r\n", err)
			return err
		}
		viewTask := &live.RecordListView{}
		task := &live.RecordList{}
		err = tx.Model(&live.RecordListView{}).Where("task_id=?", basic.TaskId).Find(&viewTask).Error
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("get RecordListView:%s", err)
			return err
		}
		err = tx.Model(&live.RecordList{}).Where("task_id=?", basic.TaskId).Find(&task).Error
		if err != nil {
			tx.Rollback()
			e.Log.Errorf("get RecordList:%s", err)
			return err
		}

		//处理结束直播按钮录制
		if viewTask.Id <= 0 && task.Id > 0 {
			s := live.RecordListView{}
			now := time.Now().Unix()
			s.TenantId = basic.TenantId
			s.BasicId = basic.Id
			s.LiveId = task.LiveId
			//s.FileId = value.Get("id").String()
			s.TaskId = basic.TaskId
			s.RecordId = task.RecordId
			s.RecordUrl = task.RecordUrl
			s.FileName = basic.LiveName
			s.FileType = task.FileType
			s.FileTime = task.FileTime
			s.Duration = task.Duration
			s.OperatorType = 1
			s.IsConfirm = basic.IsConfirm
			s.Sort = int(count + 1)
			s.CreateTime = now
			s.UpdateTime = now
			err = tx.Model(&live.RecordListView{}).Create(&s).Error
			if err != nil {
				tx.Rollback()
				e.Log.Errorf("create RecordListView error:%s \r\n", err)
				return err
			}
		}
	}

	//tx.Commit()

	return nil
}

func (e *LiveBasic) StopLiveTask(d *dto.StopLiveTaskReq) error {

	basic := live.LiveBasic{}
	err := e.Orm.Model(&live.LiveBasic{}).Where("id=?", d.Id).Find(&basic).Error
	if err != nil {
		e.Log.Errorf("get LiveBasic error:%s", err)
		return err
	}

	records := make([]live.LiveMonitorRecord, 0, 5)
	err = e.Orm.Model(&live.LiveMonitorRecord{}).Where("basic_id=?", d.Id).Find(&records).Error
	if err != nil {
		e.Log.Errorf("get LiveMonitorRecord error:%s", err)
		return err
	}
	liveId := ""
	if len(records) > 0 {
		liveId = records[0].LiveId
	}

	if len(liveId) > 0 {
		err = e.StopLive(&dto.StopLiveReq{TenantId: basic.TenantId, LiveId: liveId})
		if err != nil {
			e.Log.Errorf("StopLive error:%s", err)
			return err
		}
	}

	return nil
}

func (e *LiveBasic) RemoveLive(d *dto.StopLiveReq) error {
	err := e.StopLive(d)
	if err != nil {
		e.Log.Errorf("StopLive error:%s", err)
		return err
	}
	err = e.DeleteLive(&dto.DeleteLiveReq{TenantId: d.TenantId, LiveId: d.LiveId})
	if err != nil {
		e.Log.Errorf("DeleteLive error:%s", err)
		return err
	}
	return nil
}

func (e *LiveBasic) SavePublishSetting(d *dto.SavePublishSetting) error {

	if len(d.LogoUrl) > 0 {
		b := e.IsImageURL(d.LogoUrl)
		if !b {
			return errors.New(string(apis.ImageError.Code))
		}
	}
	now := time.Now().Unix()
	publishSetting := &live.PublishSetting{}
	e.Orm.First(&publishSetting, d.Id)
	publishSetting.TenantId = d.TenantId
	publishSetting.LiveId = d.LiveId
	publishSetting.Id = d.Id
	publishSetting.LogoUrl = d.LogoUrl
	publishSetting.Title = d.Title
	publishSetting.Introduction = d.Introduction
	publishSetting.UpdateTime = now
	if publishSetting.Id <= 0 {
		publishSetting.CreateTime = now
	}

	err := e.Orm.Save(&publishSetting).Error
	if err != nil {
		e.Log.Errorf("SavePublishSetting :%s", err)
		return err
	}
	d.Id = publishSetting.Id
	return nil
}

func (e *LiveBasic) GetPublishSetting(d *dto.GetPublishSetting) (live.PublishSetting, error) {
	publishSetting := live.PublishSetting{}
	err := e.Orm.Model(&live.PublishSetting{}).Where("live_id=?", d.Id).Find(&publishSetting).Error
	if err != nil {
		e.Log.Errorf("GetPublishSetting :%s", err)
		return publishSetting, err
	}
	return publishSetting, nil
}

func (e *LiveBasic) MoveView(d *dto.MoveViewReq) error {
	var data live.LiveMonitorRecord
	var compareData live.LiveMonitorRecord
	tx := e.Orm.Begin()

	//获取当前数据
	e.Orm.First(&data, d.Id)
	if data.Id <= 0 {
		return nil
	}
	if d.Type == 1 {
		//获取上一条数据
		e.Orm.Where("view_no<? and basic_id=?", data.ViewNo, d.BasicId).Order("view_no desc").Limit(1).Find(&compareData)
	} else {
		//获取下一条数据
		e.Orm.Where("view_no>? and basic_id=?", data.ViewNo, d.BasicId).Order("view_no asc").Limit(1).Find(&compareData)
	}
	now := time.Now().Unix()
	data.ViewNo, compareData.ViewNo = compareData.ViewNo, data.ViewNo
	err := tx.Model(&live.LiveMonitorRecord{}).Where("id=?", data.Id).Updates(map[string]interface{}{"view_no": data.ViewNo, "update_time": now}).Error
	if err != nil {
		e.Log.Errorf("MoveView error:%s \r\n", err)
		tx.Rollback()
		return err
	}
	err = tx.Model(&live.LiveMonitorRecord{}).Where("id=?", compareData.Id).Updates(map[string]interface{}{"view_no": compareData.ViewNo, "update_time": now}).Error
	if err != nil {
		e.Log.Errorf("MoveView error:%s \r\n", err)
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

func (e *LiveBasic) CreatePlatform(d *dto.CreatePlatformReq) error {

	cloudLiveService := cloudLiveService.CloudLive{}
	cloudLiveService.Log = e.Log
	cloudLiveService.Orm = e.Orm

	m := live.ThirdPush{}
	m.BasicId = d.BasicId
	m.TenantId = d.TenantId
	m.Platform = d.Platform
	m.PushUrl = d.PushUrl
	m.PushState = 2
	now := time.Now().Unix()
	m.CreateTime = now
	m.UpdateTime = now

	err := e.Orm.Model(&live.ThirdPush{}).Create(&m).Error
	if err != nil {
		e.Log.Errorf("create ThirdPush error:%s \r\n", err)
		return err
	}
	d.Id = m.Id
	return err
}

func (e *LiveBasic) UpdatePlatform(d *dto.UpdatePlatformReq) error {

	cloudLiveService := cloudLiveService.CloudLive{}
	cloudLiveService.Log = e.Log
	cloudLiveService.Orm = e.Orm
	m := live.ThirdPush{}
	err := e.Orm.Model(&live.ThirdPush{}).Where("id =? and tenant_id=?", d.Id, d.TenantId).Find(&m).Error
	if err != nil {
		e.Log.Errorf("create ThirdPush error:%s \r\n", err)
		return err
	}

	if m.Id <= 0 {
		return errors.New("未找到相关信息")
	}

	var record live.LiveMonitorRecord
	err = e.Orm.Model(&live.LiveMonitorRecord{}).Where("basic_id=?", m.BasicId).Find(&record).Error
	if err != nil {
		e.Log.Errorf("get LiveMonitorRecord error:%s \r\n", err)
		return err
	}
	if m.PushUrl != d.PushUrl {
		//先停止在创建
		if len(m.TaskId) > 0 {
			err = cloudLiveService.StopPullLive(dto.StopPullLiveReq{Id: m.TaskId, TenantId: m.TenantId})
			if err != nil {
				e.Log.Errorf("StopPullLive error:%s", err)
				return err
			}
			if m.PushState == 1 {
				source := dto.Source{}
				source.Main = record.RtmpUrl
				taskId, err := cloudLiveService.StartPullLive(dto.StartPullLiveReq{LiveId: record.LiveId, TenantId: m.TenantId, Source: source, Type: "live", PushUrl: m.PushUrl})
				if err != nil {
					e.Log.Errorf("StartPullLive error:%s", err)
				}
				if len(taskId) > 0 {
					m.TaskId = taskId
				}
			}
		}
	}
	m.Platform = d.Platform
	m.PushUrl = d.PushUrl
	m.UpdateTime = time.Now().Unix()

	err = e.Orm.Save(&m).Error
	if err != nil {
		e.Log.Errorf("save ThirdPush error:%s \r\n", err)
		return err
	}

	return err
}

func (e *LiveBasic) GetPlatformList(d *dto.GetPlatformListReq) ([]live.ThirdPush, error) {

	list := make([]live.ThirdPush, 0, 4)
	err := e.Orm.Model(&live.ThirdPush{}).Where("basic_id =?", d.BasicId).Find(&list).Error
	if err != nil {
		e.Log.Errorf("get ThirdPush error:%s \r\n", err)
		return list, err
	}

	return list, nil
}

func (e *LiveBasic) GetPlatform(d *dto.GetPlatformReq) (live.ThirdPush, error) {

	m := live.ThirdPush{}
	err := e.Orm.Model(&live.ThirdPush{}).Where("id =?", d.Id).Find(&m).Error
	if err != nil {
		e.Log.Errorf("get ThirdPush error:%s \r\n", err)
		return m, err
	}
	return m, err
}

func (e *LiveBasic) DeletePlatform(d *dto.DeletePlatformReq) error {

	cloudLiveService := cloudLiveService.CloudLive{}
	cloudLiveService.Log = e.Log
	cloudLiveService.Orm = e.Orm
	m := live.ThirdPush{}
	err := e.Orm.Model(&live.ThirdPush{}).Where("id =?", d.Id).Find(&m).Error
	if err != nil {
		e.Log.Errorf("get Platform error:%s \r\n", err)
		return err
	}
	if len(m.TaskId) > 0 {
		err = cloudLiveService.StopPullLive(dto.StopPullLiveReq{Id: m.TaskId, TenantId: m.TenantId})
		if err != nil {
			e.Log.Errorf("StopPullLive error:%s", err)
			return err
		}
	}
	err = e.Orm.Model(&live.ThirdPush{}).Where("id =?", d.Id).Delete(&m).Error
	if err != nil {
		e.Log.Errorf("DeletePlatform error:%s \r\n", err)
		return err
	}
	return err
}

func (e *LiveBasic) StartPlatform(d *dto.StartPlatformReq) error {

	cloudLiveService := cloudLiveService.CloudLive{}
	cloudLiveService.Log = e.Log
	cloudLiveService.Orm = e.Orm
	m := live.ThirdPush{}
	err := e.Orm.Model(&live.ThirdPush{}).Where("id =?", d.Id).Find(&m).Error
	if err != nil {
		e.Log.Errorf("get Platform error:%s \r\n", err)
		return err
	}

	var record live.LiveMonitorRecord
	err = e.Orm.Model(&live.LiveMonitorRecord{}).Where("basic_id=?", m.BasicId).Find(&record).Error
	if err != nil {
		e.Log.Errorf("get LiveMonitorRecord error:%s \r\n", err)
		return err
	}

	source := dto.Source{}
	source.Main = record.RtmpUrl

	taskId, err := cloudLiveService.StartPullLive(dto.StartPullLiveReq{LiveId: record.LiveId, TenantId: m.TenantId, Source: source, Type: "live", PushUrl: m.PushUrl})
	if err != nil {
		e.Log.Errorf("StartPullLive error:%s", err)
	}
	if len(taskId) > 0 {
		m.TaskId = taskId
	}

	param := make(map[string]interface{})
	param["push_state"] = 1
	param["task_id"] = taskId
	err = e.Orm.Model(&live.ThirdPush{}).Where("id =?", d.Id).Updates(&param).Error
	if err != nil {
		e.Log.Errorf("update Platform error:%s \r\n", err)
		return err
	}
	return err
}

func (e *LiveBasic) StopPlatform(d *dto.StopPlatformReq) error {

	cloudLiveService := cloudLiveService.CloudLive{}
	cloudLiveService.Log = e.Log
	cloudLiveService.Orm = e.Orm
	m := live.ThirdPush{}
	err := e.Orm.Model(&live.ThirdPush{}).Where("id =?", d.Id).Find(&m).Error
	if err != nil {
		e.Log.Errorf("get Platform error:%s \r\n", err)
		return err
	}
	if len(m.TaskId) > 0 {
		err = cloudLiveService.StopPullLive(dto.StopPullLiveReq{Id: m.TaskId, TenantId: m.TenantId})
		if err != nil {
			e.Log.Errorf("StopPullLive error:%s", err)
			return err
		}
	}
	err = e.Orm.Model(&live.ThirdPush{}).Where("id =?", d.Id).Update("push_state", 2).Error
	if err != nil {
		e.Log.Errorf("get Platform error:%s \r\n", err)
		return err
	}
	return err
}

func (e *LiveBasic) SetBlackUser(d *dto.SetBlackUserReq) error {

	imService := imService.IMService{}
	imService.Log = e.Log
	imService.Orm = e.Orm

	users := make([]live.BlackUser, 0, 5)
	dto := imDto.MultiNoSpeakReqDto{}
	dto.TenantId = d.TenantId
	dto.GroupId = d.GroupId
	for _, info := range d.UserInfos {
		user := live.BlackUser{}
		user.LiveId = d.LiveId
		user.UserId = info.UserId
		user.UserName = info.UserName
		user.UserState = 1
		user.HeadUrl = info.HeadUrl
		user.TenantId = d.TenantId
		user.BlackType = d.BlackType
		users = append(users, user)
		dto.MembersAccount = append(dto.MembersAccount, info.UserId)
	}
	if d.BlackType == 1 && len(d.GroupId) > 0 {
		dto.MuteTime = 4294967295
		err := imService.MultiNoSpeak(dto)
		if err != nil {
			e.Log.Errorf("MultiNoSpeak error:%s \r\n", err)
			return err
		}
	}

	err := e.Orm.Model(&live.BlackUser{}).Create(&users).Error
	if err != nil {
		e.Log.Errorf("create BlackUser error:%s \r\n", err)
		return err
	}

	return err
}

func (e *LiveBasic) DeleteBlackUser(d *dto.DeleteBlackUserReq) error {

	imService := imService.IMService{}
	imService.Log = e.Log
	imService.Orm = e.Orm

	users := make([]live.BlackUser, 0, 5)
	err := e.Orm.Model(&live.BlackUser{}).Where("user_id in ?", d.UserIds).Find(&users).Error
	if err != nil {
		e.Log.Errorf("get BlackUser error:%s \r\n", err)
		return err
	}

	if d.BlackType == 1 && len(d.GroupId) > 0 {
		dto := imDto.MultiNoSpeakReqDto{}
		dto.TenantId = d.TenantId
		dto.GroupId = d.GroupId
		for _, info := range users {
			dto.MembersAccount = append(dto.MembersAccount, info.UserId)
		}
		dto.MuteTime = 0
		err = imService.MultiNoSpeak(dto)
		if err != nil {
			e.Log.Errorf("MultiNoSpeak error:%s \r\n", err)
			return err
		}
	}

	err = e.Orm.Model(&live.BlackUser{}).Where("user_id in ?", d.UserIds).Delete(&users).Error
	if err != nil {
		e.Log.Errorf("delete BlackUser error:%s \r\n", err)
		return err
	}
	return err
}

func (e *LiveBasic) GetBlackUser(d *dto.GetBlackUserReq) ([]live.BlackUser, error) {

	users := make([]live.BlackUser, 0, 5)
	db := e.Orm.Model(&live.BlackUser{}).Where("live_id=?", d.LiveId)
	if d.BlackType > 0 {
		db.Where("black_type =?", d.BlackType)
	}
	err := db.Find(&users).Error
	if err != nil {
		e.Log.Errorf("get BlackUser error:%s \r\n", err)
		return users, err
	}

	return users, err
}

func (e *LiveBasic) StartPCLive(d *dto.StartPCLiveReq) (dto.StartPCLiveRes, error) {

	startPCLiveRes := dto.StartPCLiveRes{}
	vrcService := vrcService.VrcService{}
	vrcService.Log = e.Log
	mediaProcService := mediaProcService.MediaProcService{}
	mediaProcService.Log = e.Log
	var basic live.LiveBasic
	err := e.Orm.Model(&live.LiveBasic{}).Where("id=?", d.LiveId).Find(&basic).Error
	if err != nil {
		e.Log.Errorf("get LiveBasic  error:%s \r\n", err)
		return startPCLiveRes, err
	}
	startPCLiveRes.EvenId = basic.EventId
	monitors := make([]live.LiveMonitorRecord, 0, 5)
	err = e.Orm.Model(&live.LiveMonitorRecord{}).Where("basic_id=?", d.LiveId).Find(&monitors).Error
	if err != nil {
		e.Log.Errorf("get LiveMonitorRecord  error:%s \r\n", err)
		return startPCLiveRes, err
	}
	if len(monitors) <= 0 {
		return startPCLiveRes, err
	}

	if len(basic.EventId) > 0 {
		err = mediaProcService.StartMergeScreenTask(&mediaProcDto.StartMergeScreenReq{Id: basic.MergeScreenId})
		if err != nil && err.Error() != "任务已经开启" {
			e.Log.Errorf("StartMergeScreenTask error:%s \r\n", err)
			return startPCLiveRes, err
		}
		return startPCLiveRes, err
	}

	now := time.Now().Unix()
	randomNumber := rand.Intn(900000) + 100000
	startPCLiveRes.HostUserId = strconv.Itoa(randomNumber)
	res, err := vrcService.SaveRoom1(&vrcDto.SaveRoomReq{TenantId: basic.TenantId, Title: basic.LiveName, ServiceType: "22", MaxUserNum: 2, StartTime: now, ActiveType: "1", RoomType: "1", HostUserId: strconv.Itoa(randomNumber)})
	if err != nil {
		e.Log.Errorf("SaveRoom error:%s \r\n", err)
		return startPCLiveRes, err
	}
	eventId := ""
	if res != nil {
		eventId = res.EventId
	}
	startPCLiveRes.EvenId = eventId
	mPDto := &mediaProcDto.InsertMergeScreenReq{}
	mPDto.Configs = make([]mediaProcDto.MergeScreenConfig, 0, 5)
	mPDto.TaskName = basic.LiveName
	mPDto.EventId = eventId
	mPDto.StreamType = 2
	mPDto.TemplateType = 1
	mPDto.OutType = 3
	mPDto.TenantId = basic.TenantId

	pushUrlArr := strings.Split(monitors[0].PushUrl, "^^")
	if len(pushUrlArr) > 0 {
		mPDto.OutUrl = pushUrlArr[0]
	}
	mPDto.SceneInfo = "{\"width\":1280,\"height\":720,\"fps\":25,\"alt_uri\":\"\",\"vjitter\":50,\"ajitter\":50,\"delay\":0,\"enable_shadow\":false,\"shadow_rect\":{},\"layout\":1,\"volumn\":0}"
	config1 := mediaProcDto.MergeScreenConfig{}
	config1.ViewNo = 1
	config1.InputType = 1
	config1.ConfigType = "camera"
	config1.ConfigInfo = "{\"width\":320,\"height\":180,\"left\":960,\"top\":540,\"zIndex\":2,\"muted\":false,\"volume\":0}"
	config2 := mediaProcDto.MergeScreenConfig{}
	config2.ViewNo = 2
	config2.InputType = 1
	config2.ConfigType = "share"
	config2.ConfigInfo = "{\"width\":1280,\"height\":720,\"left\":0,\"top\":0,\"zIndex\":1,\"muted\":false,\"volume\":0}"
	mPDto.Configs = append(mPDto.Configs, config1)
	mPDto.Configs = append(mPDto.Configs, config2)
	id, err := mediaProcService.CreateMergeScreenTask(mPDto)
	if err != nil {
		if len(eventId) > 0 {
			err = vrcService.DeleteRoom1(&vrcDto.DeleteRoomReq{TenantId: basic.TenantId, EventId: eventId})
			if err != nil {
				e.Log.Errorf("DeleteRoom1 error:%s \r\n", err)
				return startPCLiveRes, err
			}
		}
		e.Log.Errorf("CreateMergeScreenTask error:%s \r\n", err)
		return startPCLiveRes, err
	}
	if len(basic.EventId) > 0 {
		err = mediaProcService.StartMergeScreenTask(&mediaProcDto.StartMergeScreenReq{Id: int(id)})
		if err != nil {
			e.Log.Errorf("StartMergeScreenTask error:%s \r\n", err)
			return startPCLiveRes, err
		}
	}
	param := make(map[string]interface{})
	param["event_id"] = eventId
	param["merge_screen_id"] = id
	err = e.Orm.Model(&live.LiveBasic{}).Where("id=?", d.LiveId).Updates(&param).Error
	if err != nil {
		e.Log.Errorf("update LiveBasic error:%s \r\n", err)
		return startPCLiveRes, err
	}

	return startPCLiveRes, err
}

func (e *LiveBasic) StopPCLive(d *dto.StopPCLiveReq) error {

	vrcService := vrcService.VrcService{}
	vrcService.Log = e.Log
	mediaProcService := mediaProcService.MediaProcService{}
	mediaProcService.Log = e.Log
	var basic live.LiveBasic
	err := e.Orm.Model(&live.LiveBasic{}).Where("id=?", d.LiveId).Find(&basic).Error
	if err != nil {
		e.Log.Errorf("get LiveBasic  error:%s \r\n", err)
		return err
	}
	if basic.MergeScreenId > 0 {
		err = mediaProcService.StopMergeScreenTask(&mediaProcDto.StopMergeScreenReq{Id: basic.MergeScreenId})
		if err != nil {
			e.Log.Errorf("StopMergeScreenTask  error:%s \r\n", err)
			return err
		}
	}
	return err
}

func (e *LiveBasic) GetWsList(d *vrmDto.WsListReq) (vrmDto.WsListRes, error) {

	res := vrmDto.WsListRes{}
	vrmService := vrmService.VrmService{}
	vrmService.Log = e.Log
	vrmService.Orm = e.Orm
	res, err := vrmService.WSQuery(d)
	if err != nil {
		e.Log.Errorf("GetWsList error:%s \r\n", err)
		return res, err
	}

	bindIds := make([]string, 0, 5)
	for _, r := range res.Data.List {
		bindIds = append(bindIds, r.Md5Value)
	}

	basics := make([]live.LiveBasic, 0, 4)
	err = e.Orm.Model(&live.LiveBasic{}).Where("tenant_id=? and is_delete=2 and live_type=2 and bind_id in ?", d.TenantId, bindIds).Find(&basics).Error
	if err != nil {
		e.Log.Errorf("get LiveBasic error:%s \r\n", err)
		return res, err
	}

	//s := []string{".mp4", ".mov", ".avi", ".mpg", ".mpeg", ".3gp", ".mkv", ".flv", ".ts"}

	wsListRes := vrmDto.WsListRes{}
	for k, data := range res.Data.List {
		data := data
		//d := vrmDto.List{}
		//ext := path.Ext(data.FilePath)
		//flag := false
		//for _, v := range s {
		//	if strings.Contains(v, ext) {
		//		flag = true
		//	}
		//}
		//e.Log.Trace("jahjkdkajdhkajdhkajdhkjadh:", data.FilePath, ext, flag)
		//if !flag {
		//	continue
		//}

		for _, basic := range basics {
			if data.Md5Value == basic.BindId {
				data.ImagePath = basic.LogUrl
				data.Introduction = basic.Desc
				*(&res.Data.List[k].ImagePath) = basic.LogUrl
				*(&res.Data.List[k].Introduction) = basic.Desc
			}
		}
		//d = data
		//wsListRes.Data.List = append(res.Data.List, d)
	}

	res.Data.PageIndex = d.PageIndex
	res.Data.PageSize = d.PageSize
	res.Data.Count = len(wsListRes.Data.List)
	return res, nil
}

func (e *LiveBasic) GetNeedWsList(d *vrmDto.WsListReq) (vrmDto.WsListRes, error) {

	res := vrmDto.WsListRes{}
	vrmService := vrmService.VrmService{}
	vrmService.Log = e.Log
	vrmService.Orm = e.Orm
	res, err := vrmService.WSQuery(d)
	if err != nil {
		e.Log.Errorf("GetWsList error:%s \r\n", err)
		return res, err
	}

	bindIds := make([]string, 0, 5)
	for _, r := range res.Data.List {
		bindIds = append(bindIds, r.Md5Value)
	}

	basics := make([]live.LiveBasic, 0, 4)
	err = e.Orm.Model(&live.LiveBasic{}).Where("tenant_id=? and is_delete=2 and live_type=2 and bind_id in ?", d.TenantId, bindIds).Find(&basics).Error
	if err != nil {
		e.Log.Errorf("get LiveBasic error:%s \r\n", err)
		return res, err
	}
	ids := make([]int, 0, 5)
	for _, basic := range basics {
		ids = append(ids, basic.Id)
	}

	s := []string{".mp4", ".mov", ".avi", ".mpg", ".mpeg", ".3gp", ".mkv", ".flv", ".ts"}

	wsListRes := vrmDto.WsListRes{}
	for k, data := range res.Data.List {
		d := vrmDto.List{}
		ext := path.Ext(data.FilePath)
		flag := false
		for _, v := range s {
			if strings.Contains(v, ext) {
				flag = true
			}
		}
		if !flag {
			continue
		}

		for _, basic := range basics {
			if data.Md5Value == basic.BindId {
				data.ImagePath = basic.LogUrl
				data.Introduction = basic.Desc
				*(&res.Data.List[k].ImagePath) = basic.LogUrl
				*(&res.Data.List[k].Introduction) = basic.Desc
			}
		}
		d = data
		wsListRes.Data.List = append(res.Data.List, d)
	}

	wsListRes.Data.PageIndex = d.PageIndex
	wsListRes.Data.PageSize = d.PageSize
	wsListRes.Data.Count = len(res.Data.List)

	recordViews := make([]live.RecordListView, 0, 10)
	//获取需要展示的录制文件记录
	e.Orm.Model(&live.RecordListView{}).Where("tenant_id =? and basic_id in ?", d.TenantId, ids).Find(&recordViews)

	//比较录制文件记录和需要展示的录制文件记录 将展示列表里不存在的录制文件记录取出来
	recordMaps := make(map[string]struct{})
	for _, v := range recordViews {
		key := v.RecordId
		_, ok := recordMaps[key]
		if !ok {
			recordMaps[key] = struct{}{}
		}
	}

	for k, v := range wsListRes.Data.List {
		v := v
		key := v.Md5Value
		_, ok := recordMaps[key]
		if ok {
			*(&wsListRes.Data.List[k].IsShow) = 2
		} else {
			*(&wsListRes.Data.List[k].IsShow) = 1
		}
	}

	return res, nil
}

func (e *LiveBasic) GetLiveDuration(d *dto.GetLiveDurationReq) ([]live_schedule.ScheduleRecord, error) {

	data := make([]live_schedule.ScheduleRecord, 0, 5)
	now := time.Now().Unix()
	if d.StartTime > 0 && d.EndTime > 0 {
		//获取结束时间不为空的数据
		data1 := make([]live_schedule.ScheduleRecord, 0, 5)
		db1 := e.Orm.Model(live_schedule.ScheduleRecord{}).Where("NOT ((end_time < ? OR (start_time > ?))) and end_time!=0 and type =?", d.StartTime, d.EndTime, 6)
		if len(d.TenantId) > 0 {
			db1.Where("tenant_id=?", d.TenantId)
		}

		err := db1.Find(&data1).Error
		if err != nil {
			return data, err
		}
		//获取结束时间为空的数据
		data2 := make([]live_schedule.ScheduleRecord, 0, 5)
		db2 := e.Orm.Model(live_schedule.ScheduleRecord{}).Where("NOT (start_time > ?) and end_time=0 and type =?", d.EndTime, 6)
		if len(d.TenantId) > 0 {
			db2.Where("tenant_id=?", d.TenantId)
		}
		err = db2.Find(&data2).Error
		if err != nil {
			return data, err
		}

		for k, _ := range data2 {
			*(&data2[k].EndTime) = now
		}
		data = append(data, data1...)
		data = append(data, data2...)
	}
	if d.StartTime == 0 && d.EndTime == 0 {
		err := e.Orm.Model(live_schedule.ScheduleRecord{}).Where("tenant_id = ? and type =?", d.TenantId, 6).Find(&data).Error
		if err != nil {
			return data, err
		}
		for k, _ := range data {
			if data[k].EndTime == 0 {
				*(&data[k].EndTime) = now
			}

		}
	}

	e.Log.Trace("获取统计数据", data)
	return data, nil
}

func (e *LiveBasic) GetConNum(d *dto.GetConNumReq) (bool, error) {

	vrbmService := vrbmService.VrbmService{}
	vrbmService.Log = e.Log
	vdaService := vdaService.VdaService{}
	vdaService.Log = e.Log
	var liveDuration int64
	ParanPullNum := 0
	liveNum := 0
	err, liveDuration, ParanPullNum, liveNum := GetLimitData(vrbmService, d.TenantId)
	if err != nil {
		e.Log.Errorf("GetLimitData error:%s ", err)
		return true, err
	}

	conNumStr, err := vdaService.ConCurrentConnections(d.TenantId, "私域直播")
	if err != nil {
		e.Log.Errorf("ConCurrentConnections error:%s ", err)
		return true, err
	}
	e.Log.Trace("最大直播时长：", liveDuration, "最大并发数：", ParanPullNum, "最大直播间数:", liveNum)
	conNum, _ := strconv.Atoi(conNumStr)
	e.Log.Trace("直播间人数连接数：", conNum)
	if conNum > ParanPullNum && ParanPullNum > 0 {
		return false, errors.New(string(apis.MaxParallNumError.Code))
	}
	return true, nil
}

func (e *LiveBasic) IsImageURL(url string) bool {
	// 常见的图片文件扩展名
	imageExtensions := []string{".jpg", ".jpeg", ".png", ".gif", ".psd", ".bmp", ".tga", ".tiff", ".eps", ".svg", ".pdf"}

	// 将地址转换为小写字母，方便比较
	url = strings.ToLower(url)

	// 去掉链接中的 ? 及其后面的内容
	urlParts := strings.Split(url, "?")
	urlPart := urlParts[0]

	// 检查地址是否以图片文件扩展名结尾
	for _, ext := range imageExtensions {
		if strings.HasSuffix(urlPart, ext) {
			return true
		}
	}

	return false
}
